在Python中访问void指针(使用SWIG或其他方法)
我一直在尝试使用SWIG来包装一个简单的库,这个库使用ioctl()来填充一个像下面这样的结构:
struct data
{
header* hdr;
void* data;
size_t len;
};
data是一个指向缓冲区的指针,len是这个缓冲区的长度。
我不知道怎么把data转换成Python字符串(或者数组)。另外,我还需要一种方法在析构函数中释放这个缓冲区。任何建议都非常感谢。
2 个回答
swig 提供了一个叫做 'cdata.i' 的模块。你需要在接口定义文件中包含这个模块。
一旦你包含了这个模块,它会提供两个函数:cdata() 和 memmove()。cdata() 函数可以把一个 void * 类型的二进制数据和它的长度转换成目标语言的字符串类型。而 memmove() 则是反向操作,它可以把一个字符串类型的内容(包括里面的空字节)复制到 C 语言的 void* 类型中。
有了这个模块,处理二进制数据就变得简单多了。希望这正是你需要的。
既然你在问题标题中提到“或者其他什么”,如果你选择使用 ctypes,你可以用 c_void_p
来表示一个 void*
(这是ctypes的一种基本数据类型),并且可以调用像 free
和 memcpy
这样的C语言库函数(只要这些函数可以作为DLL或.so动态库使用,现在这种情况很常见)。如果你想要一个可以修改的字符缓冲区,以便用 memcpy
复制数据,可以使用 create_string_buffer。
当然,你也可以选择使用Python的C API -- 在这种情况下,你可以使用 PyByteArray_FromStringAndSize 来从你的 void*
和长度创建一个字节数组的副本(当然,当合适的时候,你需要直接调用 free
,因为这毕竟是C代码)。
另一个可以考虑的选项是 Cython,这是一种类似Python的语言,旨在编写Python扩展等,Cython编译器可以从Cython源代码生成可编译的C代码 -- 在Cython中,你的 struct
会是:
cdef struct data:
void* hdr
void* data
unsigned int* len
假设你不想麻烦去声明 header
(也就是说,这里只关心 data
和 len
) -- 我认为 size_t
目前不在Cython中(我可能错了,他们确实在不断添加新东西;-),但 unsigned int
应该可以用。
抱歉,我已经很久没认真使用SWIG了(因为有这么多优秀的替代品) -- 如果不是因为标题中那个诱人的“或者其他什么”的说法,我可能会跳过这个问题;-)。