如何向C函数传递void指针?解决cgo的Go指针嵌套报错
解决cgo传递指针时的"cgo argument has Go pointer to Go pointer"错误
这个错误的本质是cgo的安全限制:你传递了一个指向Go指针的Go指针给C函数。Go的垃圾回收器会自主管理Go内存的分配与释放,甚至可能移动内存位置,但C代码无法感知这些操作,这种指针传递方式会引发内存安全风险,因此被cgo禁止。
解决方案:用C内存中转指针
核心思路是用C的内存分配函数存储需要传递的指针,让C函数操作C内存中的指针值,而非直接操作Go指针的指针。示例代码如下:
package main // // void test(void **data) { // // 示例操作:修改指针指向 // *data = NULL; // } import "C" import ( "unsafe" ) func main() { var data *C.void // 分配一块C内存,用来存储指针值 cMem := C.malloc(C.size_t(unsafe.Sizeof(data))) defer C.free(cMem) // 确保函数退出时释放C内存,避免泄漏 // 将Go指针的值拷贝到C内存中 *(*unsafe.Pointer)(cMem) = unsafe.Pointer(data) // 传递指向C内存的指针给C函数 C.test((**C.void)(cMem)) // 若需要,可将C函数修改后的指针值拷贝回Go变量 data = (*C.void)(*(*unsafe.Pointer)(cMem)) }
额外说明
- 如果你的C函数是要分配内存并通过输出参数返回,更简洁的方式是让C函数直接返回指针,Go代码接收后用
unsafe.Pointer转换使用,避免复杂的指针嵌套传递。 - 永远不要让C代码长期持有Go指针(包括指向Go内存的指针),Go GC无法追踪C代码持有的引用,可能导致内存被提前回收。
内容的提问来源于stack exchange,提问作者Marc Fuller
相关产品推荐
相关产品推荐

