Go与C的互相调用

First Post:

Last Update:

Word Count:
474

Read Time:
2 min

Go与C的互相调用

官方参考:https://github.com/golang/go/wiki/cgo#function-pointer-callbacks

Go调用C代码

调用C的lib

c、go代码文件如下

1
2
3
4
.
├── c_module.c
├── c_module.h
└── main.go

c_module.h

1
extern int add(int a, int b);

c_module.c

1
2
3
4
#include "c_module.h"
int add(int a, int b) {
return a+b;
}

编译为.so

1
gcc -shared -o libc_module.so c_module.c

记得在生成.so文件的名称前面加一个lib

main.go

1
2
3
4
5
6
7
8
9
10
package main
//#cgo CFLAGS: -I./
//#cgo LDFLAGS: -L${SRCDIR}/ -lc_module
//
//#include "c_module.h"
import "C"
import "fmt"
func main() {
fmt.Println(C.add(10, 5))
}

编译go代码

1
go build -o main main.go

运行

1
export LD_LIBRARY_PATH=./ && ./main

输出

1
15

调用成功

C代码调用Go代码

调用go的lib

Go语言写的代码可以编译为动态库或静态库,之后C语言链接该动态库或静态库就可以调用Go语言写的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main;
import "C"

func main() {}

//export Hello
func Hello() string {
return "Hello"
}

//export Print_a
func Print_a() {
println("aaaaa")
}

上面的//export 是一个特殊的注释,代表着导出该函数。

编译

1
go build -buildmode=c-shared -o libgo.so main.go

编译完后,会出现libgo.h 和libgo.so两个文件

如果是想静态编译的话

1
go build -buildmode=c-archive -o libgo.a main.go

编译完后,会出现libgo.h 和libgo.a两个文件

这里写一个main.c来调用go

main.c

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "libgo.h"

void main()
{
GoString str;
str = Hello();
Print_a();
printf("%d\n",(int)str.n);
}

静态库编译

1
gcc main.c libgo.a -lpthread -o main

运行

1
2
3
./main
aaaaa
5

成功的打印了aaaaa以及字符串的长度。

动态库编译

1
2
export LD_LIBRARY_PATH=./
gcc main.c -L./ -lgo -lpthread -o main

查看链接情况

1
2
3
4
5
6
ldd main
linux-vdso.so.1 (0x00007ffc22882000)
libgo.so => ./libgo.so (0x00007ff893c0f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff893a13000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff8939f0000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff893d63000)

正常的,运行

1
2
3
./main
aaaaa
5
打赏点小钱
支付宝 | Alipay
微信 | WeChat