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. PAT 团体程序设计天梯赛-练习集 L1-017. 到底有多二

    一个整数“犯二的程度”定义为该数字中包含2的个数与其位数的比值.如果这个数是负数,则程度增加0.5倍:如果还是个偶数,则再增加1倍.例如数字“-13142223336”是个11位数,其中有3个2,并且 ...

  2. javase

    http://blog.csdn.net/itlwc/article/category/1572517 http://blog.csdn.net/itlwc

  3. 关于Cocos2dx之JS创建项目

    环境: cocos2dx -3.10 ndk - r9 sdk 1.进入到指定的项目的目标目录下面去,然后执行cocos new -l js ProjectName 进入对应目录查看:

  4. 核心梳理——消息处理的骨架流程——ESFramework 4.0 进阶(02)

    在ESFramework 4.0 概述一文中,我们提到ESFramework.dll作为通信框架的核心,定义了消息处理的骨架流程,本文我们来详细剖析这个流程以及该骨架中所涉及的各个组件.ESFrame ...

  5. Logistic Regression:银行贷款申请审批实例

    问题定义 这是一个贷款的审批问题,假设你是一个银行的贷款审批员,现在有客户需要一定额度的贷款,他们填写了个人的信息(信息在datas.txt中给出),你需要根据他们的信息,建立一个分类模型,判断是否可 ...

  6. redhat 时区修改

    修改系统时区,发现只需要一个命令就可以解决 修改之前: cp /usr/share/zoneinfo/Asia/Chongqing  /etc/localtime 修改之后:

  7. ejabberd聊天室离线消息

    首先,xmpp服务器是基于ejabberd.离线消息模块是mod_interact,原地址地址:https://github.com /adamvduke/mod_interact: 修改后实现群聊离 ...

  8. redis高级实用特性(2)

    事务处理: redis对事务的支持目前还是比较简单,redis只能保证一个 client发起事务中的命令可以连续执行,而中间不会插入其他 client的命令,当一个client 在一个连接中发出mul ...

  9. 第四题 (List)写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列。 例如:  List list = new ArrayList();  list.add(“Hello”);  list.add(“World”);  list.add(“Learn”); //此时list 为Hello World Learn  r

    package zuoye; import java.util.ArrayList; import java.util.List; public class Reverse01 { public st ...

  10. KVM 虚拟化基本搭建

    KVM虚拟化技术 KVM是基于x86架构上Linux操作系统的全虚拟化解决方案 ,在Centos6.3系统中,kvm已经被集成到内核中,相当于使用内核来做虚拟机管理程序.由于KVM本身就工作于内核环境 ...