From 4f611e892a7e57a0af2305830e69825a77e50293 Mon Sep 17 00:00:00 2001 From: chai2010 Date: Thu, 11 Jan 2018 03:20:46 +0800 Subject: [PATCH] =?UTF-8?q?ch2-06:=20=E5=88=9D=E7=A8=BF=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SUMMARY.md | 2 +- ch2-cgo/ch2-06-static-shared-lib.md | 179 ++++++++++++++++++++++++++-- 2 files changed, 168 insertions(+), 13 deletions(-) diff --git a/SUMMARY.md b/SUMMARY.md index ca10a37..14c2baf 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -15,7 +15,7 @@ * [2.3. CGO编程基础](ch2-cgo/ch2-03-basic.md) * [2.4. CGO内存模型](ch2-cgo/ch2-04-memory.md) * [2.5. C++类包装](ch2-cgo/ch2-05-class.md) - * [2.6. 静态库和动态库(Doing)](ch2-cgo/ch2-06-static-shared-lib.md) + * [2.6. 静态库和动态库](ch2-cgo/ch2-06-static-shared-lib.md) * [2.7. Go实现Python模块(TODO)](ch2-cgo/ch2-07-py-module.md) * [2.8. SWIG(TODO)](ch2-cgo/ch2-08-swig.md) * [2.9. 补充说明(TODO)](ch2-cgo/ch2-09-faq.md) diff --git a/ch2-cgo/ch2-06-static-shared-lib.md b/ch2-cgo/ch2-06-static-shared-lib.md index 785b425..0eb1752 100644 --- a/ch2-cgo/ch2-06-static-shared-lib.md +++ b/ch2-cgo/ch2-06-static-shared-lib.md @@ -139,23 +139,178 @@ $ dlltool -dllname number.dll --def number.def --output-lib libnumber.a ## 导出C静态库 +CGO不仅可以使用C静态库,也可以将Go实现的函数导出为C静态库。我们现在用Go实现前面的number库的莫加法函数。 + +创建number.go,内容如下: + +```go +package main + +import "C" + +func main() {} + +//export number_add_mod +func number_add_mod(a, b, mod C.int) C.int { + return (a + b) % mod +} +``` + +根据CGO文档的要求,我们需要在main包中导出C函数。对于C静态库构建方式来说,会忽略main包中的main函数,只是简单导出C函数。采用以下命令构建: + +``` +$ go build -buildmode=c-archive -o number.a +``` + +在生成number.a静态库的同时,cgo还会生成一个number.h文件。 + +number.h文件的内容如下(为了便于显示,内容做了精简): + +```c +#ifdef __cplusplus +extern "C" { +#endif + +extern int number_add_mod(int p0, int p1, int p2); + +#ifdef __cplusplus +} +#endif +``` + +其中`extern "C"`部分的语法是为了同时适配C和C++两种语言。核心内容是声明了要导出的number_add_mod函数。 + +然后我们创建一个`_test_main.c`的C文件用于测试生成的C静态库(用下划线作为前著名是让go build构建C静态库时忽略这个文件): + +```c +#include "number.h" + +#include + +int main() { + int a = 10; + int b = 5; + int c = 12; + + int x = number_add_mod(a, b, c); + printf("(%d+%d)%%%d = %d\n", a, b, c, x); + + return 0; +} +``` + +通过以下命令编译并运行: + +``` +$ gcc -o a.out _test_main.c number.a +$ ./a.out +``` + +使用CGO创建静态库的过程非常简单。 + ## 导出C动态库 +CGO导出动态库的过程和静态库类似,只是将构建模式改为`c-shared`,输出文件名改为`number.so`而已: + +``` +$ go build -buildmode=c-shared -o number.so +``` + +`_test_main.c`文件内容不变,然后用以下命令编译并运行: + +``` +$ gcc -o a.out _test_main.c number.so +$ ./a.out +``` + ## 导出非main包的函数 -## Plugin +通过`go help buildmode`命令可以查看C静态库和C动态库的构建说明: -静态注入 -C动态库注入 -Goplugin特性 +``` +-buildmode=c-archive + Build the listed main package, plus all packages it imports, + into a C archive file. The only callable symbols will be those + functions exported using a cgo //export comment. Requires + exactly one main package to be listed. -