如何让 void** 成为 C 库的参数?

我正在尝试使用 cgo 从 GO 调用 C 库。


C 库具有以下功能:


int receive(void** data);


// I'd call it like that:

void* myptr; // myptr=null

int nbBytes = receive(&myptr);

if (nbBytes==0) { return }

// myptr has now an address to a valid buffer that contains nbBytes bytes.


// And then casting it with char* to access the data that can be anything. Example:

printf("%d", *(char*)myptr);

如何receive()从 GO 调用此函数?Go 不分配任何内存,内存地址通过它返回myptr并直接从中访问。

  • receive()是“无副本”并将实际数据的地址写入myptr. 然后使用 访问数据*(char*)myptr

  • 我们可以假设receive()分配和释放缓冲区,它对 lib 的用户隐藏

理想情况下,我会通过[]bytein go 读取数据。


偶然的你
浏览 60回答 1
1回答

隔江千里

您的问题中没有足够的信息来完全回答它,因为我们不知道——C 语言本身并没有告诉我们——它void **是如何使用的。您的评论和附加代码(非常强烈地)表明它的使用方式是receive填充指针:int receive(void **data) {&nbsp; &nbsp; *data = <something>;&nbsp; &nbsp; return <some value>;}我们不知道尖括号的部分;要使用 C 代码中的这些数据,我们会按照您所说的做:void f(void) {&nbsp; &nbsp; void *p;&nbsp; &nbsp; int ret;&nbsp; &nbsp; ...&nbsp; &nbsp; ret = receive(&p);}鉴于这么多和(合理的)假设,我们不知道的是:ret值说明什么?p之后总是有效吗?可以访问多少字节*p?例如,将:struct our_data dst;memcpy(&dst, p, len);p是从数据结构中获取字节的有效方法dst,如果是这样,长度len从何而来?它是否暗示,例如,我们是否知道因为retwas not -1(error)p是有效的并且有sizeof(struct our_data)可用的字节,我们需要 memcpy 来使其正确对齐?如果我们知道所有这些事情,我们就可以直接从 Go 完成这项工作:var p unsafe.Pointervar obj C.struct_our_dataret := C.receive(&p)C.memcpy(unsafe.Pointer(&obj), p, len) // or similar with copy()尽管可能(取决于任务等)为原始数据编写一个反序列化器更有意义,我们将其作为一个存在于 C 内存中的数组获得;
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go