http://blog.ralch.com/tutorial/golang-sharing-libraries/

Sharing Golang packages to C and Go

Sun, Aug 23, 2015

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 are the following options:

  • archive: Build the listed non-main packages into .a files. Packages named main are 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 that they import, into C shared libraries.
  • shared: Combine all the listed non-main packages into a single shared library.
  • exe: Build the listed main packages and everything they import into executables. Packages not named main are ignored.

By default, listed main packages are built into executables and listed non-main packages are built into .a files.

In this article we will explore two major ways to share libraries between Go and C:

Using shared library in Go

Assume that GOPATH contains this structure:

.
├── calc
│   └── calc.go
└── cashier
└── main.go

The calc package contains a set of functions that do arithmetic opertaions:

// filename: calc.go
package calc func Sum(x, y int) int {
return x + y
}

Before compile any shared library, the standard builtin packages should be installed as shared library. This will allow any other shared library to link with them.

$ go install -buildmode=shared -linkshared std

Then the calc package 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 be from $GOPATH/src.

Lets use the shared library calc in the cashier application:

// package: cashier
// filename: main.go
package main import "calc"
import "fmt" func main() {
fmt.Println("Cashier Application")
fmt.Printf("Result: %d\n", calc.Sum(5, 10))
}

The application should be compiled and linked with calc library with the following command:

$ go build -linkshared -o app cashier

The output of executing the application is:

$ ./app
Cashier Application
Result: 15

Note that this feature is available on linux/amd64 platform or when gccgo compiler is used.

Using shared Go library in C

Go functions can be executed from C applications. They should be exported by using the following comment line:

//export <your_function_name>

In the code snippet below, the function SayHello and SayBye are exported:

// package name: nautilus
package main import "C"
import "fmt" //export SayHello
func SayHello(name string) {
fmt.Printf("Nautilus says: Hello, %s!\n", name)
} //export SayBye
func 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 be 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 will produce a static/dynamic C library nautilus.a and 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 GoInt64 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 __cplusplus
extern "C" {
#endif extern void SayHello(GoString p0); extern void SayBye(); #ifdef __cplusplus
}
#endif

The header file nautilus.h shoulde be imported from every C application that executed SayHello and SayBye functions.

In the example below, the SayHello function is 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:

$ ./wale
This 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 best from both worlds. This provides to a legacy system a modern language that can improve their maintainance costs and business needs. It maximize code reusability in the Go ecosystem.

go share library的更多相关文章

  1. Different ways to invoke a shared object/share library(.so)

    在Linux中调用.so文件的方法有几种. 1.直接在编译的时候链接上. 2.dlopen/???

  2. eclipse 启动报share library load faild

      eclipse 与 jdk 版本要一致 *32 - 对应32位 *64 - 对应64位

  3. 浅析C/C++ library

    1 背景 原来跑的好好的进程,重启后没跑多少就挂掉了,奇怪了.经过跟踪,原来是加载了一个.so文件,于是决定学习一下library相关的东东,现在和大家分享一下. 2 分类 C/C++ library ...

  4. 如何使用event 10049分析定位library cache lock and library cache pin

    Oracle Library Cache 的 lock 与 pin 说明 一. 相关的基本概念 之前整理了一篇blog,讲了Library Cache 的机制,参考: Oracle Library c ...

  5. APP漏洞扫描用地址空间随机化

    APP漏洞扫描用地址空间随机化 前言 我们在前文<APP漏洞扫描器之本地拒绝服务检测详解>了解到阿里聚安全漏洞扫描器有一项静态分析加动态模糊测试的方法来检测的功能,并详细的介绍了它在针对本 ...

  6. Linux文件与目录管理

    .      代表此层目录 . .     代表上一层目录 -      代表前一个工作目录 ~     代表"目前用户身份"所在的中文件夹 ~account   代表accoun ...

  7. Android NDK之JNI陷阱

    背景: 最近一个月一直在做移植库的工作,将c代码到share library移植到Android平台.这就涉及到Android NDK(native develop kit)内容.这里只想记录下JNI ...

  8. 【原创】Capture CIS利用Access数据库建立封装库说明

    1.在服务器端建立新空间,方便封装库以及数据库的归档存放 服务器路径:\\192.168.1.234\Share\STG_LIB,文件夹内容如下,其中Datesheet存放物料数据手册,Pcb_Lib ...

  9. MySQL CMake参数说明手册

    MySQL自5.5版本以后,就开始使用CMake编译工具了,因此,你在安装源文件中找不到configure文件是正常的.很多人下到了新版的MySQL,因为找不到configure文件,不知道该怎么继续 ...

随机推荐

  1. hdu1015

    #include <stdio.h>#include <string.h>#include <stdlib.h> int cmp(void* a, void* b) ...

  2. 《JS权威指南学习总结--7.10 数组类型》

    内容要点: 一.数组类型 判断它是否为数组通常非常有用.在ES5中,可以使用Array.isArray()函数来做这件事情: Array.isArray([]); //=>true Array. ...

  3. javascript 拖放效果

    最近一直在看javascript的书籍,有些东西在书上看着貌似理解了,但是在真正动手实践时,其实有些细节你根本不了解.所以看起来就算是一个简单的效果,写起来也未必简单,就算写起来简单,写的代码也未必规 ...

  4. OpenCV2.x自学笔记——自适应阈值

    adaptiveThreshold(src,dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, do ...

  5. 朱丽叶—Cuda+OSG

    #include <cuda_runtime.h> #include <osg/Image> ; typedef struct cuComplex { float r; flo ...

  6. Where is the python library installed?

    configure: error: Could not link test program to Python. Maybe the main Python library has been inst ...

  7. Linux系统安装建议

    1.推荐使用CentOS-6.x 64位版本:2.分区,推荐分出/usr/local用来存放应用程序./data分区用来存放数据,具体分区建议如下:/boot 100Mswap 4096M (视内存大 ...

  8. js中的随机数

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. ThinkPHP框架基础

    ThinkPHP 一.php框架基础介绍 真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维 ...

  10. lua: Learning Official Doc notes

    dynamically typed vars: basic types: nil, boolean, number, string, function, userdata, thread & ...