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. 第三章 Netty入门应用

    3.1 Netty开发环境的搭建 3.1.1 下载Netty的软件包 3.1.2 搭建Netty应用工程 3.2 Netty服务端开发 3.3 Netty客户端开发 3.4 运行和调试 3.4.1 服 ...

  2. JS复习:第二十章

    一.JSON 1.JSON的语法可以表示以下三种类型的值: (1)简单值:字符串.数值.布尔值和null.如:5,“Hello,World!” (2)对象:javascript中对象字面量: var ...

  3. 【Sort】HeapSort

    堆排序,时间复杂度O(N log N),实际使用中慢于使用Sedgewick增量的增量排序. 大致思路: 1.先在数组中建堆,如果是增量排序,则需要建一个大堆 2.每循环一次,把最大的数,也就是num ...

  4. hdu 2993 MAX Average Problem(斜率DP入门题)

    题目链接:hdu 2993 MAX Average Problem 题意: 给一个长度为 n 的序列,找出长度 >= k 的平均值最大的连续子序列. 题解: 这题是论文的原题,请参照2004集训 ...

  5. Python创建多进程,用Queue传递信息

    创建10个进程,分别计算0到1000各个区间的和,主进程汇总 __author__ = 'Administrator' # -*- coding:utf-8 -*- ''' @author:qiush ...

  6. css3制作字体

    代码教程 HTML代码用H1吧,这样语义化好些,因为标题一般用h1-h6. <h1 class="vintage">美丽的中国语</h1> 纯CSS制作的复 ...

  7. debian root 可以远程登陆

    vim /etc/ssh/sshd_config FROM: PermitRootLogin without-password TO: PermitRootLogin yes

  8. NOIP2010-普及组复赛-第一题-数字统计

    题目描述 Description 请统计某个给定范围[L, R]的所有整数中,数字 2 出现的次数. 比如给定范围[2, 22],数字 2 在数 2 中出现了 1 次,在数 12 中出现 1 次,在数 ...

  9. 【其他】MySql数据库的安装与卸载

    一.安装 1.首先下载安装包,包含服务端和客户端 2.添加用户组.用户 secondary1:~ # groupadd mysql secondary1:~ # useradd -g mysql -d ...

  10. 通过实例来理解ajax

    点击一个按钮,然后将信息显示到指定的div内. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"& ...