Explain
When you compile code using the go build or go install commands, you can use the -buildmode l to specify what file to generate.
go build -buildmode=<mode> perhaps go install -buildmode=<mode>
Use go help buildmode l to view all supported buildmodel options.
-buildmode=archive Build the listed non-main packages into .a files. Packages named main are ignored. -buildmode=c-archive Build the listed main package, plus all packages it imports, into a C archive file. The only callable symbols will be those functions exported using a cgo //export comment. Requires exactly one main package to be listed. -buildmode=c-shared Build the listed main package, plus all packages it imports, into a C shared library. The only callable symbols will be those functions exported using a cgo //export comment. Requires exactly one main package to be listed. -buildmode=default Listed main packages are built into executables and listed non-main packages are built into .a files (the default behavior). -buildmode=shared Combine all the listed non-main packages into a single shared library that will be used when building with the -linkshared option. Packages named main are ignored. -buildmode=exe Build the listed main packages and everything they import into executables. Packages not named main are ignored. -buildmode=pie Build the listed main packages and everything they import into position independent executables (PIE). Packages not named main are ignored. -buildmode=plugin Build the listed main packages, plus all packages that they import, into a Go plugin. Packages not named main are ignored.
Under the classification instructions:
-
-buildmode=shared is used to generate libraries that are used during go compilation and compilation, conceptually similar to dynamic libraries in the c language. The option-linkshared is required to compile go files using these libraries.
-
-buildmode=c-archive and-buildmode=c-shared are used to generate libraries and header files for C, corresponding to static libraries and dynamic libraries, respectively.
-
-buildmode=plugin is used to generate dynamic libraries that can be loaded while the go language is running (currently only loaded, not uninstalled, can they be uninstalled by destroying the protocol?)
Several other options are temporarily unclear.
Compile go script to C language library
Compiling go source code into a C language library requires the following conditions
- Compile options using -buildmode=c-archive or -buildmode=c-shared
- main package is required in compilation source
- Source must import "C"
- The export symbol is in the main package with //export NAME on the previous line
Since the exported symbols can only be located in the main package, the main() function must be defined, but it can be empty. Moreover, the parameters and return value types of the exported function can only use the golang base type, and complex types such as structs inside the go language cannot be used.
Now define a simple go file to generate a library for the C language
package main import ( "C" "fmt" ) //export hello func hello(num int32, name string, size float32) uint8 { fmt.Printf("Hello, world, %v, %v, %v\n", num, name, size) return 0 } func main() { fmt.Printf("Hello, in main.\n") hello(1, "Yuan", 3.14) }
Under Direct Run Test:
$ go run main.go Hello, in main. Hello, world, 1, Yuan, 3.14
Now generate libraries that the C language can call:
$ go build -buildmode=c-archive -o hello.a main.go $ ls go.mod hello.a hello.h main.go
As you can see, two files have been generated: hello.a and hello.h. Partners in C language development are certainly new.
go generated header file
Let's see what's in the header file generated in the last step:
/* Code generated by cmd/cgo; DO NOT EDIT. */ /* package command-line-arguments */ #line 1 "cgo-builtin-export-prolog" #include <stddef.h> /* for ptrdiff_t below */ #ifndef GO_CGO_EXPORT_PROLOGUE_H #define GO_CGO_EXPORT_PROLOGUE_H #ifndef GO_CGO_GOSTRING_TYPEDEF typedef struct { const char *p; ptrdiff_t n; } _GoString_; #endif #endif /* Start of preamble from import "C" comments. */ /* End of preamble from import "C" comments. */ /* Start of boilerplate cgo prologue. */ #line 1 "cgo-gcc-export-header-prolog" #ifndef GO_CGO_PROLOGUE_H #define GO_CGO_PROLOGUE_H typedef signed char GoInt8; typedef unsigned char GoUint8; typedef short GoInt16; typedef unsigned short GoUint16; typedef int GoInt32; typedef unsigned int GoUint32; typedef long long GoInt64; typedef unsigned long long GoUint64; typedef GoInt64 GoInt; typedef GoUint64 GoUint; typedef __SIZE_TYPE__ GoUintptr; typedef float GoFloat32; typedef double GoFloat64; typedef float _Complex GoComplex64; typedef double _Complex GoComplex128; /* static assertion to make sure the file is being used on architecture at least with matching size of GoInt. */ typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; #ifndef GO_CGO_GOSTRING_TYPEDEF typedef _GoString_ GoString; #endif typedef void *GoMap; typedef void *GoChan; typedef struct { void *t; void *v; } GoInterface; typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; #endif /* End of boilerplate cgo prologue. */ #ifdef __cplusplus extern "C" { #endif extern GoUint8 hello(GoInt32 num, GoString name, GoFloat32 size); #ifdef __cplusplus } #endif
You can see that the basic types in the go language have been redefined by typedef, where GoString is slightly more complex and is designated as a structure with pointers and lengths:
#ifndef GO_CGO_GOSTRING_TYPEDEF typedef struct { const char *p; ptrdiff_t n; } _GoString_; #endif #ifndef GO_CGO_GOSTRING_TYPEDEF typedef _GoString_ GoString; #endif
Calling the golang-generated Library in C
Now write a simple C file that calls the hello() function from the library you just generated.
#include <stdio.h> #include "hello.h" int main() { GoInt32 num = 3; GoFloat32 size = 3.14; GoString name = {0}; name.p = "Yuan"; name.n = 4; //Length of string above GoUint8 ret = hello(num, name, size); printf("ret=%d\n", ret); return 0; }
Now compile and run:
$ mv hello.a libhello.a $ gcc hello_test_go.c -L ./ -l hello -lpthread $ ./a.out Hello, world, 3, Yuan, 3.14 ret=0
As you can see, the functions in the go language run perfectly.
Reference material
C-source archive mode (c-archive) static library mode for Go language compilation mode