This is a creation in Article, where the information may have evolved or changed.
Sharing Golang packages to C and Go
Sun, 23, 2015
Programming Languages Tutorial
The latest Go 1.5 version is out. As part of the new features, Go compiler can compile packages as a shared libraries.
It accepts -buildmode argument that determines how a package is compiled. These is the following options:
archive: Build the listed Non-main packages into. a files. Packages named Main is ignored.
c-archive: Build the listed main package, plus all packages it imports, into a C archive file.
c-shared: Build the listed main packages, plus all packages this they import, into C shared libraries.
shared: Combine all the listed Non-main packages to a single shared library.
exe: Build the listed main packages and everything they import into executables. Packages not named Main is ignored.
By default, listed main packages is built into executables and listed Non-main packages is built into. a files.
In this article we'll explore the major ways to share libraries between Go and C:
Using Shared Library in Go
Assume GOPATH that contains this structure:
.├── calc│ └── calc.go└── cashier └── main.go
The package calc contains a set of functions this do arithmetic opertaions:
// filename: calc.gopackage calcfunc Sum(x, y int) int { return x + y}
Before compile any GKFX library, the standard builtin packages should is installed as shared library. This would allow any of the other shared libraries to link with them.
$ go install -buildmode=shared -linkshared std
Then the calc "can be compiled" as shared library linked to std libraries:
$ go install -buildmode=shared -linkshared calc
Due to a issue, building and installing shared library should is from $GOPATH/src .
Lets Use the shared library in the calc cashier application:
// package: cashier// filename: main.gopackage mainimport "calc"import "fmt"func main() { fmt.Println("Cashier Application") fmt.Printf("Result: %d\n", calc.Sum(5, 10))}
The application should is compiled and linked with the library with the calc following command:
$ go build -linkshared -o app cashier
The output of executing the application is:
$ ./appCashier ApplicationResult: 15
Note that this feature are available on linux/amd64 platform or if gccgo compiler is used.
Using shared Go Library in C
Go functions can executed from C applications. They should is exported by using the following comment line:
//export <your_function_name>
In the code snippet below, the function and is SayHello SayBye exported:
// package name: nautiluspackage mainimport "C"import "fmt"//export SayHellofunc SayHello(name string) {fmt.Printf("Nautilus says: Hello, %s!\n", name)}//export SayByefunc SayBye() {fmt.Println("Nautilus says: Bye!")}func main() {// We need the main function to make possible// CGO compiler to compile the package as C shared library}
The packaged should is compiled with buildmode flags c-shared or c-archive :
// as c-shared library$ go build -buildmode=c-shared -o nautilus.a nautilus.go
// as c-archive $ go build -buildmode=c-archive -o nautilus.a nautilus.go
As result the GO compiler would produce a static/dynamic C library and nautilus.a header file nautilus.h . The header file contains type definitions that Marshall and Unmarshall data between Go and C :
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 G OInt64 goint;typedef GoUint64 gouint;typedef __size_type__ gouintptr;typedef float gofloat32;typedef double GoFloat64; typedef __complex FLOAT Gocomplex64;typedef __complex double gocomplex128;typedef struct {char *p; Goint N; } gostring;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 __cplusplusextern "C" {#endifextern void SayHello (gostring p0); extern void Saybye (); #ifdef __cplusplus} #endif /code>
The header file nautilus.h Shoulde is imported from every C application, that executed and SayHello SayBye functions.
In the example below, the SayHello function was called with parameter of type GoString . It includes char* field and its length.
// filename: _wale.c#include "nautilus.h"#include <stdio.h>int main() { printf("This is a C Application.\n"); GoString name = {"Jack", 4}; SayHello(name); SayBye(); return 0;}
The _wale.c file is compiled with the following command:
$ gcc -o _wale _wale.c nautilus.a
Execution produce the following output:
$ ./waleThis is a C Application.Nautilus says: Hello, Jack!Nautilus says: Bye!
Conclusion
Sharing libraries between C and Go gives opportunity to build greater and better application by using the Both worlds. This provides to a legacy system a modern language the can improve their maintainance costs and business needs. It Maximize code reusability in the Go ecosystem.