In addition to its compact syntax and good concurrency support, Go has the advantage of being able to call C code. You can write C code directly in Go source code, or you can refer to external libraries in C. This allows you to rewrite the language where there are performance bottlenecks, or where certain features are missing in Go and third parties but are readily available in C. This way, you can rewrite the code where performance bottlenecks are encountered, or some features are missing in Go and third parties, but C language has ready-made libraries that you can use directly. The official Cgo blog https://blog.golang.org/c-go-cgo and the command line documentation https://golang.org/cmd/cgo/ explain Cgo, but some parts of it are not clear enough or are not mentioned.
Inline C code
The following example writes C code directly to the Go source code by introducing a non-existent package C
, and then writing the C code on top of the introduction, noting that it can only be written on top of the C
package. A method add
is defined, which is then used in the Go code via C.add.
Separate C source code
Smaller C code can be easily used by inlining, but larger code can be written independently of C code.
-
Directory structure:
-
foo.h
1
int add(int, int);
-
foo.c
-
main.go
The above example splits the C code into foo.h and foo.c. Go code just needs to introduce foo.h
to call the add
method.
If the main package refers to more than one file, you can’t run it with the go run command, you have to use go build. go build detects the files referenced by cgo, and the .c .h files are compiled together.
Calling external libraries
Directory structure:
The C code is the same as before, but moved to the foo directory to force Go not to compile them. Assume that foo is the external library we need to use.
Compile the static library first, generating the libfoo.a
static link library in the foo directory.
-
main.go
Calling external libraries requires the #cgo
pseudo directive, which can specify compilation and linking parameters, such as CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS and LDFLAGS. CFLAGS can configure C compiler parameters, where -I can specify the header directory, such as “-I/path/to/include”. LDFLAGS can be configured to refer to libraries, where -L specifies the directory of the referenced library and -l specifies the library name. If the referenced header file or library is in the default system directory (e.g. /usr/include, /usr/local/include and /usr/lib, /usr/local/lib) then the directory can be left unspecified.
The #cgo
directive can have platform-restricted arguments, e.g. for linux or darwin platforms only, see https://golang.org/pkg/go/build/#hdr-Build_Constraints for details. You can also use ${SRCDIR}
instead of the source directory.
Two tips for array pointers
C often uses array pointers as arguments and return values, the following example shows how Go creates an array pointer and converts an array pointer to a slice.
|
|