Fork me on GitHub

Go build模式之c-archive,c-shared,linkshared

本文用实例介绍这3种模式的构建方法;

go程序中需要被导出的方法Hello():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//hello.go
package main

import "C"
import "fmt"

func main() {
Hello("hello")
}

//export Hello
func Hello(name string) {
fmt.Println("output:",name)
}

注意事项:

1.//export Hello,这是约定,所有需要导出给 C 调用的函数,必须通过注释添加这个构建信息,否则不会构建生成 C 所需的头文件;

2.导出函数的命名的首字母是否大写,不受go规则的影响,大小写均可;

3.头部必须添加import “C”;

c-archive模式:
1
$go build --buildmode=c-archive  hello.go

编译生成hello.a和C头文件hello.h

在所生成的 hello.h 的头文件中,我们可以看到 Go 的 Hello() 函数的定义:

1
2
3
4
5
6
7
8
9
#ifdef __cplusplus
extern "C" {
#endif
...
extern void Hello(GoString p0);
...
#ifdef __cplusplus
}
#endif

在头文件中GoString的定义如下:

1
2
3
4
5
6
typedef struct { 
const char *p;
ptrdiff_t n;
} _GoString_;

typedef _GoString_ GoString;

然后我们可以在 hello.c 中引用该头文件,并链接Go编译的静态库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>
#include "hello.h"

int main(int argc, char *argv[]){
char *type = argv[1];
char buf[] = "test for ";
char input[16]={0};

sprintf(input, "%s %s", buf, type);

GoString str;
str.p = input;
str.n = strlen(input);

Hello(str);
return 0;
}

然后,构建 C 程序:

1
$gcc  -o hello_static hello.c hello.a -lpthread
c-shared模式:
1
$go build --buildmode=c-shared -o libhello.so  hello.go

编译生成libhello.so

构建c程序,并链接动态库

1
$gcc  -o hello_dynamic hello.c  -L./   -lhello -lpthread

-L 指定链接库为当前目录

-l 指定所需要连接的动态库名称,去掉lib前缀和.so后缀

linkshared模式:

该模式主要用于为go程序编译动态链接库

1
2
$sudo /usr/local/go/bin/go install -buildmode=shared std
$sudo /usr/local/go/bin/go build -linkshared -o hello_linkshared hello.go

编译生成hello_linkshared可执行程序

附上实例程序编译脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# !/bin/bash

# static
go build --buildmode=c-archive hello.go
gcc -o hello_static hello.c hello.a -lpthread
echo "=== run static binary ==="
./hello_static static

# dynamic
go build --buildmode=c-shared -o libhello.so hello.go
gcc -o hello_dynamic hello.c -L./ -lhello -lpthread
echo "=== run dynamic binary ==="
./hello_dynamic dynamic

# linkshared for go
sudo /usr/local/go/bin/go install -buildmode=shared std
sudo /usr/local/go/bin/go build -linkshared -o hello_linkshared hello.go
echo "=== run linkshared binary ==="
ls -lh ./hello_linkshared
./hello_linkshared

# default , static for go
go build -o hello_static_go hello.go
ls -lh ./hello_static_go
./hello_static_go

输出:

您的鼓励是我持之以恒的动力