为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
偶然的你 2022-10-24 09:06:38
我正在尝试使用 cgo 从 GO 调用 C 库。C 库具有以下功能:int receive(void** data);// I'd call it like that:void* myptr; // myptr=nullint 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 读取数据。
查看完整描述

1 回答

?
隔江千里

TA贡献1906条经验 获得超10个赞

您的问题中没有足够的信息来完全回答它,因为我们不知道——C 语言本身并没有告诉我们——它void **是如何使用的。您的评论和附加代码(非常强烈地)表明它的使用方式是receive填充指针:


int receive(void **data) {

    *data = <something>;

    return <some value>;

}

我们不知道尖括号的部分;要使用 C 代码中的这些数据,我们会按照您所说的做:


void f(void) {

    void *p;

    int ret;

    ...

    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.Pointer

var obj C.struct_our_data

ret := C.receive(&p)

C.memcpy(unsafe.Pointer(&obj), p, len) // or similar with copy()

尽管可能(取决于任务等)为原始数据编写一个反序列化器更有意义,我们将其作为一个存在于 C 内存中的数组获得;

查看完整回答
反对 回复 2022-10-24
  • 1 回答
  • 0 关注
  • 59 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信