如何在go中将指针传递给切片到C函数
背景:使用cgo从Golang调用C函数。
我想使用具有此签名的C函数: int f(int *count, char ***strs)
。 它将修改count
和strs
的数据,这就是它使用指针的原因。 count
的值是strs
的长度; strs
是一个字符串数组; 返回值只是一个(布尔)指示符,指示是否存在错误。
在golang中,我可以通过使用Cf((*C.int)(&count))
成功传递和修改count
; 使用[]*C.char
传递[]string
。 示例代码如下:
/* #include int f(int *c, char **str) { int i; printf("%d\n", *c); for (i = 0; i < *c; i++) { printf("%s\n", str[i]); } *c = (*c) + 1; return 1; } */ import "C" func go_f(strs []string) int { count := len(strs) c_count := C.int(count) c_strs := make([]*C.char, count) for index, value := range strs { c_strs[index] = C.CString(value) defer C.free(unsafe.Pointer(c_strs[index])) } err := Cf(&c_argc, (**C.char)(&c_argv[0])) return int(err) }
如你所见,C函数目前是int f(int *c, char **str)
,但我想要的是int f(int *c, char ***str)
。
这就是说:我真正想要的是在C中启用对字符串数组的修改(例如resize)并将其转回Go字符串片,这样我仍然可以在Go中使用它。
这该怎么做? 我已经搜索并试验了一段时间,但没有运气。
Go切片既在Go中分配,又在C数组中分配不同的数据结构,因此您无法将其传递给C函数(cgo也会阻止您执行此操作,因为切片包含Go指针)
您需要在C中分配数组以便在C中操作数组。就像使用C.CString一样,您还需要跟踪释放外部数组的位置,尤其是在C函数可能分配新数组的情况下。
cArray := C.malloc(C.size_t(c_count) * C.size_t(unsafe.Sizeof(uintptr(0)))) // convert the C array to a Go Array so we can index it a := (*[1<<30 - 1]*C.char)(cArray) for index, value := range strs { a[index] = C.CString(value) } err := Cf(&c_count, (***C.char)(unsafe.Pointer(&cArray)))