golang中调用c的正确姿势工程结构如上图所示go调用c语言的动态库,go调用c语言的动态库我们需要实现的目标是在go文件中调用c文件
foo.c如下:
foo.go如下
foo.h如下:
编译过程如下:
1、先将c文件编译为.o文件go调用c语言的动态库,然后生成动态链接库.dylib文件
(1) clang -c foo.c
(2 clang -shared foo.o -o libfoo.dylib
2、在上述的动态链接库生成之后,在foo.go中添加动态链接命令:#cgo LDFLAGS: -L./ -lfoo
需要注意的是
中间不能有空格
go语言如何调用c函数直接嵌入c源代码到go代码里面
package main
/*
#include stdio.h
void myhello(int i) {
printf("Hello C: %d\n", i);
}
*/
import "C"
import "fmt"
func main() {
C.myhello(C.int(12))
fmt.Println("Hello Go");
}
需要注意的是C代码必须放在注释里面
import "C"语句和前面的C代码之间不能有空行
运行结果
$ go build main.go./main
Hello C: 12
Hello Go
分开c代码到单独文件
嵌在一起代码结构不是很好看,很多人包括我,还是喜欢把两个分开,放在不同的文件里面 , 显得干净,go源文件里面是go的源代码 , c源文件里面是c的源代码 。
$ ls
hello.chello.hmain.go
$ cat hello.h
void hello(int);
$ cat hello.c
#include stdio.h
void hello(int i) {
printf("Hello C: %d\n", i);
}
$ cat main.go
package main
// #include "hello.h"
import "C"
import "fmt"
func main() {
C.hello(C.int(12))
fmt.Println("Hello Go");
}
编译运行
$ go build./main
Hello C: 12
Hello Go
编译成库文件
如果c文件比较多,最好还是能够编译成一个独立的库文件,然后go来调用库 。
$ find mylib main
mylib
mylib/hello.h
mylib/hello.c
main
main/main.go
编译库文件
$ cd mylib
# gcc -fPIC -shared -o libhello.so hello.c
编译go程序
$ cd main
$ cat main.go
package main
// #cgo CFLAGS: -I../mylib
// #cgo LDFLAGS: -L../mylib -lhello
// #include "hello.h"
import "C"
import "fmt"
func main() {
C.hello(C.int(12))
fmt.Println("Hello Go");
}
$ go build main.go
运行
$ export LD_LIBRARY_PATH=../mylib
$ ./main
Hello C: 12
Hello Go
在我们的例子中,库文件是编译成动态库的,main程序链接的时候也是采用的动态库
$ ldd main
linux-vdso.so.1 =(0x00007fffc7968000)
libhello.so = ../mylib/libhello.so (0x00007f513684c000)
libpthread.so.0 = /lib64/libpthread.so.0 (0x00007f5136614000)
libc.so.6 = /lib64/libc.so.6 (0x00007f5136253000)
/lib64/ld-linux-x86-64.so.2 (0x000055d819227000)
理论上讲也是可以编译成整个一静态链接的可执行程序,由于我的机器上缺少静态链接的系统库 , 比如libc.a,所以只能编译成动态链接 。
go如何动态调用方法go如何动态调用方法
package main
import (
"fmt"
"reflect"
)
type X struct{}
func (X) Test(x, y int) (int ,error) {
return x + y , fmt.Errorf("err: %d", x+y)
}
func main() {
var a X
v := reflect.ValueOf(a)
m := v.MethodByName("Test")
in := []reflect.Value{
reflect.ValueOf(1),
reflect.ValueOf(2),
}
out := m.Call(in)
for _, v := range out {
fmt.Println(v)
}
}
//输出3err:3
//对于变参来说 , 用callslice更好
package main
import (
"fmt"
"reflect"
)
type X struct{}
func (X) Format(s string,a ...interface{}) string {
推荐阅读
- 新手养鱼什么鱼缸最好视频,新手养鱼什么鱼缸最好视频教学
- js转json字符串,js json 转字符串
- 360游戏开发者平台,360开发人员工具中文
- 推荐几款恋爱养成游戏手游,恋爱养成游戏有哪些好玩的
- c语言求方程的解函数 c语言如何解方程
- 荣耀20可以升级鸿蒙了么,荣耀20能升鸿蒙吗
- 如何用数字制作ppt海报,数字ppt怎么做
- rpg单机游戏什么好玩,rpg单机游戏什么好玩的
- c语言中有哪些特殊函数 c语言中的特殊运算符