我一直在尝试使用 SWIG 来包装一个简单的库,该库使用 ioctl() 来填充如下结构:
struct data
{
header* hdr;
void* data;
size_t len;
};
data是指向缓冲区的指针,len是该缓冲区的长度。
我无法弄清楚如何将数据转换为 Python 字符串(或数组)。此外,我需要一种方法来释放析构函数中的缓冲区。任何建议表示赞赏。
swig 提供了一个名为“cdata.i”的模块。您应该将其包含在接口定义文件中。
一旦你包含它,它就会提供两个函数 cdata() 和 memmove()。给定一个 void * 和二进制数据的长度,cdata() 将其转换为目标语言的字符串类型。memmove() 是相反的。给定一个字符串类型,它会将字符串的内容(包括嵌入的空字节)复制到 C void* 类型中。
使用此模块处理二进制数据变得非常简单。我希望这是你需要的。
由于您在 Q 的标题中说“或其他”-如果您选择使用ctypes,您可以表示一个void*
with c_void_p
(ctypes 的基本数据类型之一,并从 C 运行时库访问诸如free
and之类memcpy
的函数(只要后者可作为 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
我相信,此时它不是 Cython 的一部分(我可能是错的,他们确实在不断添加东西; -),但可能可以。len
size_t
unsigned int
抱歉,自从我认真使用 SWIG 以来已经太久了(有所有这些优秀的替代品)——如果不是因为标题中那个诱人的“或其他”子句,我会跳过 Q;-)。