cgo笔记二:C代码模块化

前言:这也是我记录cgo笔记的初衷,我偶尔需要把同事的c代码拿来用(白嫖),又不想展示自己可怜的C代码水平(毕竟没时间研究代码),so...

C代码模块化

这还是使用原作者(go语言高级编程)的一个例子,抽象一个名为hello的模块,模块的全部接口函数都在hello.h头文件定义:

//hello.h
void SayHello(const char* s);
// hello.c
#include "hello.h"
#include <stdio.h>

void SayHello(const char* s) {
    puts(s);
}
package main

/*
#include <hello.h>
*/
import "C"

func main() {
    C.SayHello(C.CString("Hello, Worldn"))
}

使用 go run . 进行运行发现程序可以正常运行。go mod可能会报错,初始化go mod即可。

静态库

如果有源码的情况下最好,但是也有时候,同事不给源码,只给库文件,这个时候就需要我们做相关调用了
我们先用纯C语言构造一个简单的静态库。我们要构造的静态库名叫number,库中只有一个number_add_mod函数,用于表示数论中的模加法运算。number库的文件都在number目录下。
number/number.h头文件只有一个纯C语言风格的函数声明:

//源码:《go语言高级编程》
//number/number.h
int number_add_mod(int a, int b, int mod);

number/number.c对应函数的实现:

//源码:《go语言高级编程》
#include "number.h"
int number_add_mod(int a, int b, int mod) {
    return (a+b)%mod;
}

因为CGO使用的是GCC命令来编译和链接C和Go桥接的代码。因此静态库也必须是GCC兼容的格式。
通过以下命令可以生成一个叫libnumber.a的静态库:

$ cd ./number
$ gcc -c -o number.o number.c
$ ar rcs libnumber.a number.o

创建main.go文件如下:

package main

//#cgo CFLAGS: -I./number
//#cgo LDFLAGS: -L${SRCDIR}/number -lnumber
//
//#include "number.h"
import "C"
import "fmt"

func main() {
    fmt.Println(C.number_add_mod(10, 5, 12))
}

其中有两个#cgo命令,分别是编译和链接参数。CFLAGS通过-I./number将number库对应头文件所在的目录加入头文件检索路径。LDFLAGS通过-L${SRCDIR}/number将编译后number静态库所在目录加为链接库检索路径,-lnumber表示链接libnumber.a静态库。需要注意的是,在链接部分的检索路径不能使用相对路径(C/C++代码的链接程序所限制),我们必须通过cgo特有的${SRCDIR}变量将源文件对应的当前目录路径展开为绝对路径(因此在windows平台中绝对路径不能有空白符号)
因为我们有number库的全部代码,所以我们可以用go generate工具来生成静态库,或者是通过Makefile来构建静态库。因此发布CGO源码包时,我们并不需要提前构建C静态库。

动态库

上面的源码,编译成动态库

$ cd number
$ gcc -shared -o libnumber.so number.c

因为动态库和静态库的基础名称都是libnumber,只是后缀名不同而已。因此Go语言部分的代码和静态库版本完全一样:

package main

//#cgo CFLAGS: -I./number
//#cgo LDFLAGS: -L${SRCDIR}/number -lnumber
//
//#include "number.h"
import "C"
import "fmt"

func main() {
    fmt.Println(C.number_add_mod(10, 5, 12))
}

编译时GCC会自动找到libnumber.a或libnumber.so进行链接。当然根据我的实际情况,我基本上不需要动态库链接。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容