go cgo struct
对于CGO来说,方式
typedef struct libfacedetection_capi_face_t libfacedetection_capi_face_t;
typedef struct libfacedetection_capi_result_t libfacedetection_capi_result_t;
struct libfacedetection_capi_face_t {
int x;
int y;
int w;
int h;
int neighbors;
int angle;
};
现代所有主流操作系统几乎都是用 C 语音实现的,几乎所有高级语言都能调用 C 语言,例如 PHP 可以调用 C 语言写的 PHP 扩展,Python 也可以调用 C 语言实现的 Python 扩展。 Golang 语言也不例外。
Golang 通过 CGO 机制能很方便的调用 C 语言。本文介绍一下如何在 Go 中调用稍稍复杂一点 C 函数,例如: char* f(int, int*)
首先看一个最简单的例子,将 Golang 中的一个字符串传入 C 函数中:
package main
import "C"
import "unsafe"
func main() {
s := "Hello Cgo"
cs := C.CString(s) // golang字符串转换成 char * ;原理是在C中通过 malloc 分配c内存,并将字符串复制过去
defer C.free(unsafe.Pointer(cstr))
C.print(cs)
}
注意:
上述程序中的关键语句cs := C.CString(s)
是将一个 Golang 的字符串转换为 C 语言字符串,
该 C 语言字符串是由 C 函数 malloc 从堆中分配的,因此后续需要调用 C.free
释放内存。
2. 函数调用
然后,我们看看如何调用一个复杂一点的 C 函数?例如: char* f(int, int*)
,返回一个char*
指针,并且有一个参数也是返回值int*
。请直接看下面的例子:
package main
import "C"
import "unsafe"
import "fmt"
func main() {
rlen := C.int(0) //返回C中的int变量
len := 10
cstr := C.xmalloc(C.int(len), &rlen)
defer C.free(unsafe.Pointer(cstr))
gostr := C.GoStringN(cstr, rlen) // cstring 转换成 gostring
fmt.Printf("retlen=%v\n", rlen)
println(gostr)
}
xmalloc
函数的第二个参数是int*
,这里设计为一个输入、输出参数。我们在 Golang 中使用 C.int 类型的指针就可以; 其返回值是一个char*
,
在 Golang 中就是 *C.char
,由于返回值是指针,其内存由 malloc 分配,因此需要在 Golang 中对其内存进行释放。
3. 结构体
再然后,我们看看如何调用一个返回结构体的 C 函数?例如:struct MyString xmalloc(int len)
。请看示例代码:
package main
import "C"
import "unsafe"
import "fmt"
func main() {
len := 10
str := C.xmalloc(C.int(len))
defer C.free(unsafe.Pointer(str.s))
gostr := C.GoStringN(str.s, str.len)
fmt.Printf("retlen=%v\n", str.len)
println(gostr)
}