2 回答

TA贡献1828条经验 获得超6个赞
如果要使用第一种方法,则需要在函数调用参数之外创建切片,并避免临时分配的切片头或参数中的外部结构,因此cgo检查不会将其视为存储在 Go 中的指针.
b := buf.Bytes()
rc := C.the_function(unsafe.Pointer(&b[0]), C.int(buf.Len()))
该C.CString方法将更安全,因为数据被复制到 C 缓冲区中,因此没有指向 Go 内存的指针,并且后面的切片bytes.Buffer不会被修改或超出范围。您需要转换整个字符串,而不仅仅是第一个字节。这种方法确实需要分配和复制两次,但是如果数据量很小,与 cgo 调用本身的开销相比,这可能不是问题。
str := buf.String()
p := unsafe.Pointer(C.CString(str))
defer C.free(p)
rc = C.the_function(p, C.int(len(str)))
如果该解决方案中不能接受数据的 2 个副本,则还有第三种选择,您可以自己分配 C 缓冲区,并将单个副本复制到该缓冲区中:
p := C.malloc(C.size_t(len(b)))
defer C.free(p)
// copy the data into the buffer, by converting it to a Go array
cBuf := (*[1 << 30]byte)(p)
copy(cBuf[:], b)
rc = C.the_function(p, C.int(buf.Len()))
但是对于后两种选择,不要忘记释放 malloc 的指针。

TA贡献1725条经验 获得超8个赞
您的程序崩溃是因为在 go1.6 中将指针传递给 C 的规则发生了变化(有关详细信息,请参阅https://tip.golang.org/doc/go1.6#cgo)。
我不知道你的程序为什么会崩溃,所以我创建了 Go issue https://github.com/golang/go/issues/14546。
但是不管这个问题的答案如何,我都不会使用内部位bytes.Buffer
(就像你一样)直接传递给 cgo。该bytes.Buffer
实现可以改变未来,你程序将启动破神秘。我只是将您需要的数据复制到任何合适的结构中,然后使用它传递给 cgo。
- 2 回答
- 0 关注
- 448 浏览
添加回答
举报