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.