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. Storm-0.9.0.1安装部署 指导

    可以带着下面问题来阅读本文章: 1.Storm只支持什么传输 2.通过什么配置,可以更改Zookeeper默认端口 3.Storm UI必须和Storm Nimbus部署在同一台机器上,UI无法正常工 ...

  2. Spring Security(12)——Remember-Me功能

    目录 1.1     概述 1.2     基于简单加密token的方法 1.3     基于持久化token的方法 1.4     Remember-Me相关接口和实现类 1.4.1    Toke ...

  3. 关于wcf中一些重要词语解释

    From a distant view, the service offers an                                                        

  4. hdu_3247_Resource Archiver(AC自动机+bfs+TSP)

    题目链接:hdu_3247_Resource Archiver 题意: 有n个资源串,m个病毒串,现在要将所有的资源串整合到一个串内,并且这个串不能包括病毒串,问最短的串长为多少 题解: 将资源串和病 ...

  5. Cmake常用指令

    1. cmake_minimum_required(VERSION 2.8)           检查cmake的版本,至少为2.8 2. project(helloworld)           ...

  6. NSDictionary 的内部实现

    NSDictionary是IOS中使用的一种key-value容器,参考cocotron的源代码,NSDictionary使用NSMapTable实现. NSMapTable同样是一个key-valu ...

  7. 理解WebKit和Chromium(电子书)

    前言   基础篇 WebKit, WebKit2, Chromium和Chrome介绍 WebKit和Blink WebKit和Chromium代码目录结构介绍 WebKit和Chromium功能模块 ...

  8. Python之异步IO&RabbitMQ&Redis

    协程: 1.单线程运行,无法实现多线程. 2.修改数据时不需要加锁(单线程运行),子程序切换是线程内部的切换,耗时少. 3.一个cpu可支持上万协程,适合高并发处理. 4.无法利用多核资源,因为协程只 ...

  9. .Net Core 读取appsettings.json的配置

    在.net core中是没有*.config 文件的 配置文件都是*.json 1.在project.json里下面这行代码 "Microsoft.Extensions.Options.Co ...

  10. Openjudge-计算概论(A)-过滤多余的空格

    描述: 一个句子中也许有多个连续空格,过滤掉多余的空格,只留下一个空格. 输入一行,一个字符串(长度不超过200),句子的头和尾都没有空格.输出过滤之后的句子. 样例输入 Hello world.Th ...