Go语言学习之cgo(golang与C语言相互调用)
生命不止,继续 go go go !!! 几乎所有的编程语言都有C语言的影子,当然golang也不例外。可以看到golang的创始者们与c language有着密切的联系。所有,golang和c语言的相互调用也是理所应当。 什么场合会使用Go与C的互操作呢? CgoCgo enables the creation of Go packages that call C code. Cgo lets Go packages call C code. Given a Go source file written with some special features,cgo outputs Go and C files that can be combined into a single Go package. 这个不要误解,cgo不是一个package,我们只需要import “C”就好了。 Package unsafe 顺便介绍一下unsafe包。 Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines. 指针类型: *类型:普通指针,用于传递对象地址,不能进行指针运算。 unsafe.Pointer:通用指针类型,用于转换不同类型的指针,不能进行指针运算。 uintptr:用于指针运算,GC 不把 uintptr 当指针,uintptr 无法持有对象。uintptr 类型的目标会被回收。 unsafe.Pointer 可以和 普通指针 进行相互转换。 也就是说 unsafe.Pointer 是桥梁,可以让任意类型的指针实现相互转换,也可以将任意类型的指针转换为 uintptr 进行指针运算。 golang调用C语言直接上代码了: package main
// typedef int (*intFunc) ();
//
// int
// bridge_int_func(intFunc f)
// {
// return f();
// }
//
// int fortytwo()
// {
// return 42;
// }
import "C"
import "fmt"
func main() {
f := C.intFunc(C.fortytwo)
fmt.Println(int(C.bridge_int_func(f)))
}
如果编译遇到错误: 输出: 来点有难度的: package main
// typedef int (*intFunc) ();
//
// int
// bridge_int_func(intFunc f)
// {
// return f();
// }
//
// int fortytwo()
// {
// return 42;
// }
import "C"
import "fmt"
func main() {
f := C.intFunc(C.fortytwo)
fmt.Println(int(C.bridge_int_func(f)))
}
是不是有点蒙圈,这跟上面的代码有什么区别呢?但是当你编译的时候: 切记,在注释和import”C”之间不能有空行 golang中使用c语言中的数据类型数值类型 C.char, 指针类型 * 字符串类型* 通过C.CString函数,我们可以将Go的string类型转换为C的”字符串”类型,再传给C函数使用。就如我们在本文开篇例子中使用的那样: s := “Hello Cgon” 数组类型 package main
// int cArray[] = {1,2,3,4,5,6,7};
import "C"
import "fmt"
import "unsafe"
func CArrayToGoArray(cArray unsafe.Pointer,size int) (goArray []int) {
p := uintptr(cArray)
for i := 0; i < size; i++ {
j := *(*int)(unsafe.Pointer(p))
goArray = append(goArray,j)
p += unsafe.Sizeof(j)
}
return
}
func main() {
goArray := CArrayToGoArray(unsafe.Pointer(&C.cArray[0]), 7)
fmt.Println(goArray)
}
在c中调用golang代码直接上代码: package main
/* extern void myprint(int i); void dofoo(void) { int i; for (i=0;i<10;i++) { myprint(i); } } */
import "C"
import "fmt"
//export myprint
func myprint(i C.int) {
fmt.Printf("i = %vn",uint32(i))
}
func DoFoo() {
C.dofoo()
}
func main() {
DoFoo()
}
很遗憾,出现了错误: 修改,拆分成两个文件: package main
/* extern void myprint(int i); void dofoo(void) { int i; for (i=0;i<10;i++) { myprint(i); } } */
import "C"
func main() {
C.dofoo()
}
foo.go: package main
import "C"
import "fmt"
//export myprint
func myprint(i C.int) {
fmt.Printf("i = %vn",uint32(i))
}
参考链接: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |