在Python中访问void指针(使用SWIG或其他方法)

0 投票
2 回答
3092 浏览
提问于 2025-04-15 19:47

我一直在尝试使用SWIG来包装一个简单的库,这个库使用ioctl()来填充一个像下面这样的结构:

struct data
{
  header* hdr;
  void* data;
  size_t len;
};

data是一个指向缓冲区的指针,len是这个缓冲区的长度。

我不知道怎么把data转换成Python字符串(或者数组)。另外,我还需要一种方法在析构函数中释放这个缓冲区。任何建议都非常感谢。

2 个回答

2

swig 提供了一个叫做 'cdata.i' 的模块。你需要在接口定义文件中包含这个模块。

一旦你包含了这个模块,它会提供两个函数:cdata() 和 memmove()。cdata() 函数可以把一个 void * 类型的二进制数据和它的长度转换成目标语言的字符串类型。而 memmove() 则是反向操作,它可以把一个字符串类型的内容(包括里面的空字节)复制到 C 语言的 void* 类型中。

有了这个模块,处理二进制数据就变得简单多了。希望这正是你需要的。

1

既然你在问题标题中提到“或者其他什么”,如果你选择使用 ctypes,你可以用 c_void_p 来表示一个 void*(这是ctypes的一种基本数据类型),并且可以调用像 freememcpy 这样的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(也就是说,这里只关心 datalen) -- 我认为 size_t 目前不在Cython中(我可能错了,他们确实在不断添加新东西;-),但 unsigned int 应该可以用。

抱歉,我已经很久没认真使用SWIG了(因为有这么多优秀的替代品) -- 如果不是因为标题中那个诱人的“或者其他什么”的说法,我可能会跳过这个问题;-)。

撰写回答