如何让 void** 成为 C 库的参数?
How to get a void** to be a parameter of a C library?
我正在尝试使用 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);
如何从 GO 调用此 receive()
函数? Go 不分配任何内存,内存地址通过 myptr
返回并直接从中访问。
receive()
是一个“无拷贝”并将实际数据的地址写入 myptr
。然后使用 *(char*)myptr
. 访问数据
- 我们可以假设
receive()
分配和释放缓冲区,它对库的用户是隐藏的
理想情况下,我会通过 []byte
读取数据。
[编辑:您添加了一个说明,说明这不仅仅是建议。但是我们仍然不知道这些数据之后是如何使用的,来自C代码。]
您的问题中没有足够的信息来完整回答它,因为我们不知道——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
从何而来?是否暗示,例如,我们是否知道因为 ret
不是 -1
(错误),所以 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 内存中的数组获得;参见,例如 How to convert [1024]C.char to [1024]byte.
我正在尝试使用 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);
如何从 GO 调用此 receive()
函数? Go 不分配任何内存,内存地址通过 myptr
返回并直接从中访问。
receive()
是一个“无拷贝”并将实际数据的地址写入myptr
。然后使用*(char*)myptr
. 访问数据
- 我们可以假设
receive()
分配和释放缓冲区,它对库的用户是隐藏的
理想情况下,我会通过 []byte
读取数据。
[编辑:您添加了一个说明,说明这不仅仅是建议。但是我们仍然不知道这些数据之后是如何使用的,来自C代码。]
您的问题中没有足够的信息来完整回答它,因为我们不知道——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
从何而来?是否暗示,例如,我们是否知道因为 ret
不是 -1
(错误),所以 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 内存中的数组获得;参见,例如 How to convert [1024]C.char to [1024]byte.