CGO basis

Minimalist CGO program

// hello.go
package main

import "C"

func main() {
    println("hello cgo")
}

Code via import "C"enable CGO characteristic statement, the main function Go built only through printlnthe output string functions, and there are no related code and CGO. Although there is no call related functions CGO, but the go buildcommand will start the gcc compiler to compile and link phase, this is a complete program of CGO.

Standard C library function based on the output string

// hello.go
package main

//#include <stdio.h>
import "C"

func main() {
    C.puts(C.CString("Hello, World\n"))
}
We not only through import "C"enabled CGO characteristic statement, contains the C language <stdio.h>header file. Then by CGO package C.CStringfunction Go language string to C strings, the last call CGO package C.putsfunction prints a C string converted to standard output window.

Compared to the "Hello, World Revolution" the biggest difference in a program CGO is: we do not release the C language string C.CString created before the program exits; and we use puts function to print directly to standard output, before using fputs is printed to standard output.
No release C.CString created using C language strings cause a memory leak. But for this small programs, this is no problem, because the operating system will automatically recover all the resources of the program after the program exits.

Use your own C functions

// hello.go
package main

/*
#include <stdio.h>

static void SayHello(const char* s) {
    puts(s);
}
*/
import "C"

func main() {
    C.SayHello(C.CString("Hello, World\n"))
}
In addition SayHellofunction is implemented outside our own, another example of the front portion and substantially similar. We can also SayHellofunction into a C language source file in the current directory (suffix must be .c). Because C is prepared in a separate file, in order to allow external references, it is necessary to remove the function staticmodifier.
// hello.c

#include <stdio.h>

void SayHello(const char* s) {
    puts(s);
}
Then CGO part declare SayHelloa function, other parts of the same:
/ hello.go
package main

//void SayHello(const char* s);
import "C"

func main() {
    C.SayHello(C.CString("Hello, World\n"))
}
Note that if the command is run before go run hello.goor go build hello.goso, here must be used go run "your/package"or go build "your/package"can. If present in the path, then the packet may be run directly go run .orgo build .

Since SayHello function has been placed in a separate file in the C, we naturally can file the corresponding C compiler package for use as a static library or DLL file. If the library is static or dynamic library reference SayHello function, it needs to be moved out of the corresponding C source files in the current directory (CGO builder automatically builds a C source file in the current directory, resulting in a C function name conflict)

Modular C code

During programming, abstraction and modularity is to simplify complex issues of common tools. When the long code statement change, we can encapsulate code similar to the one function; when a program function is increased, the function will be split into different files or modules. The core is modular programming (interface language of the interface are not Go here, but the concept of the API) program oriented programming interface
In the previous example, we can abstract a module called hello, all of the interface of the function module in hello.hthe definition of the header file:
// hello.h
void SayHello(const char* s);
Only one statement SayHello function. But as a user hello module, you can safely use SayHello function without caring about the function of the specific implementation. As implementers SayHello function, the function to achieve as long as you can meet the specifications declared in the header file function. The following is a C language implementation SayHello function, corresponding to hello.cthe file:
// hello.c

#include "hello.h"
#include <stdio.h>

void SayHello(const char* s) {
    puts(s);
}
In the hello.cbeginning of the file, implementers through #include "hello.h"statements include statements SayHello function, so you can ensure implementation of the interface function module to meet publicly.
Hello.h interface files and users to achieve a common agreement hello module, but this convention is not required to use C language to achieve SayHello function. We can also use C++language to re-implement the C language functions:
// hello.cpp

#include <iostream>

extern "C" {
    #include "hello.h"
}

void SayHello(const char* s) {
    std::cout << s;
}
In SayHello function implementation in C ++ version, C ++ through our unique std::coutoutput stream output string. However, in order to ensure the SayHello function implemented in C ++ language to meet the C language header file hello.h specification defines the function, we need to extern "C"indicate the link symbol of the function follow the rules of the C language statements.
After facing the C API interface programming language uses, we achieve the complete liberation of the module's language shackles: implementors can use any programming language module, as long as the final agreement to meet the public API. We can use C language SayHello function, you can also 使用更复杂的C++语言来实现SayHello函数, of course, we can also use汇编语言甚至Go语言来重新实现SayHello函数
Re-implement the C function with the Go
In fact, it not just for CGO Go for calling C language functions can also be used to derive Go to the C language function language function calls. In the previous example, we have abstract a module called hello, all the interfaces are defined in the function module hello.h header file:
// hello.h
void SayHello(/*const*/ char* s);
Now we create a hello.go file, re-implement the function SayHello C language interface using the Go language:
// hello.go
package main

import "C"

import "fmt"

//export SayHello
func SayHello(s *C.char) {
    fmt.Print(C.GoString(s))
}

We CGO's //export SayHelloinstruction function SayHello Go language is exported as C language functions. To adapt CGO exported C language function, we prohibit the const qualifier in the declaration of a function. It should be noted that there are actually two versions of the SayHello function: a Go locale; the other is a C language environment. cgo generated C language version SayHello function will eventually call the Go language version of the code by bridging function SayHello

By programming interfaces for C language, we are not only the liberation of the implementors functions, while also simplifying the user function. Now we can use as a function SayHello (use and puts functions similar to) a standard library:
package main

//#include <hello.h>
import "C"

func main() {
    C.SayHello(C.CString("Hello, World\n"))
}
Everything seems back to the beginning of the code CGO, but the code connotation richer.

Go programming interface for C

In the case began, we all CGO Go code in a file. Then, technology for the C programming interface SayHello are split into different files C, while the main document is still Go. Then again, with Go function SayHello function to re-implement the C language interface. But for the present example is only one function, to be split into three different files does have some cumbersome.
As the saying goes, it tends to divide together for a long, long period of division, we are now trying to examples of several files into one Go back file. The following is the result of the merger:
package main

//void SayHello(char* s);
import "C"

import (
    "fmt"
)

func main() {
    C.SayHello(C.CString("Hello, World\n"))
}

//export SayHello
func SayHello(s *C.char) {
    fmt.Print(C.GoString(s))
}
CGO now scaled version of the code in C language code has been very small, but we can still thought to Go further to refine the language of our CGO code. By analyzing the parameters can be found SayHello function if the string can be used directly Go is the most direct. In the CGO Go1.10 adds a new predefined _GoString_ C language type representing Go language string. The following codes are improved
// +build go1.10

package main

//void SayHello(_GoString_ s);
import "C"

import (
    "fmt"
)

func main() {
    C.SayHello("Hello, World\n")
}

//export SayHello
func SayHello(s string) {
    fmt.Print(s)
}
Although it looks all Go language code, but when the main function is to start the implementation of the Go language, the C language version SayHello bridging function CGO automatically generated, and finally back to the function SayHello Go locale. This code contains the essence of CGO programming, the reader needs in-depth understanding.

Guess you like

Origin www.cnblogs.com/binHome/p/12625764.html