c - 使用 CGo 调用具有双指针输出参数的 C 函数
问题描述
我正在尝试找出调用此函数的正确方法:
size_t
fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap)
{
if (datap)
*datap = (buf ? buf->data : NULL);
return (buf ? buf->len : 0);
}
使用 CGo 获取底层字符串及其长度作为 Go 中的字节数组。
这是正确的方法吗?
var bufferContents *C.uchar
length := C.fz_buffer_storage(ctx, buf, &bufferContents)
bytes := C.GoBytes(unsafe.Pointer(bufferContents), C.int(length))
由于 C 代码覆盖*datap
,我不确定垃圾收集器是否仍然会做正确的事情。
我在这里看到了一个答案,暗示了一些类似的东西
var tempUcharPtr *C.uchar
bufferContents := C.malloc(C.size_t(unsafe.Sizeof(tempUcharPtr)))
defer C.free(bufferContents)
length := C.fz_buffer_storage(ctx, buf, (**C.uchar)(bufferContents))
bytes := C.GoBytes(unsafe.Pointer(*(**C.uchar)(bufferContents)), C.int(length))
这似乎也有效,但它更加复杂,我想知道它是否比以前的版本更好/更安全。
解决方案
显然,第一个版本很好。引用文档:
Go 代码可以将 Go 指针传递给 C,前提是它指向的 Go 内存不包含任何 Go 指针。
据我了解,由于var bufferContents *C.uchar
将初始化为 nil,因此对于上述规则,它不算作“Go 指针”。以下简化的代码示例证实了这一点:
package main
// void F(char **p) {}
import "C"
func main() {
var p *C.char = new(C.char)
C.F(&p)
}
将触发“恐慌:运行时错误:cgo 参数的 Go 指针指向 Go 指针”
package main
// void F(char **p) {}
import "C"
func main() {
var p *C.char
C.F(&p)
}
工作得很好,即使设置GODEBUG=cgocheck=2
.
感谢 Gophers Slack 社区 #cgo 频道上的人们帮助我理解这一点!
推荐阅读
- teradata - Teredata:在提交删除行时创建违规表 xxx;开始事务,结束事务,不返回
- angular - Observables 的异步处理
- html - 如何使按钮水平对齐
- web-crawler - 如何使用stormcrawler从网站抓取特定数据
- java - 在加工中绘制形状
- c# - 在 Visual Studio 中通过代码添加新的 Nuget 包源
- vb.net - 比较两个 Richtextboxes 中的文本并获取差异
- python - JSONDecodeError:预期值:TD Ameritrade API 中的第 2 行第 11 列(字符 11)
- c# - 不应该发生关于异步的编译器警告
- javascript - 如何在 JavaScript 中加入具有不同分隔符的数组?