go怎么调用c语言动态库 go语言调用c语言

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() {
【go怎么调用c语言动态库 go语言调用c语言】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
//对于变参来说go怎么调用c语言动态库,用callslice更好
package main
import (
"fmt"
"reflect"
)
type X struct{}
func (X) Format(s string,a ...interface{}) string {
return fmt.Sprintf(s,a...)
}
func main() {
var a X
v := reflect.ValueOf(a)
m := v.MethodByName("Format")
out := m.Call([]reflect.Value{
reflect.ValueOf("%s = %d"),
reflect.ValueOf("x"),
reflect.ValueOf(100),//所有参数都须处理
})
fmt.Println(out)
out = m.CallSlice([]reflect.Value{
reflect.ValueOf("%s = %d"),
reflect.ValueOf([]interface{}{"x", 100}),//仅一个[]interface{}即可
})
//无法调用非导出方法go怎么调用c语言动态库,无法获取有效地址
fmt.Println(out)
}
//输出[x=100][x=100]
---------------------------------------------
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)

推荐阅读