在 Python 3.x 代码中暴露 C 字符串而不复制

7 投票
2 回答
849 浏览
提问于 2025-04-16 11:55

我有一个用Cython写的库,它封装了一个C语言库,我把一些C字符串暴露给Python代码。这些字符串很大,而且是静态的(不能释放内存),所以直接把它们转换成Python字符串(这会复制一份)就不行了——我会遇到内存不足的错误。

目前我已经在Python 2.x上用旧的缓冲区API搞定了这段代码,基本上是这样的:

def get_foo():
     return PyBuffer_FromMemory(c_foo_ptr,c_foo_len)

这在Python 2.x上运行得很好,但在3.x中旧的缓冲区API已经不再使用了,我不知道该怎么用新的API来实现同样的功能。

我看到有PyMemoryView_FromBufferPyBuffer_FillInfo这两个函数,结合起来应该能实现相同的效果,但PyBuffer_FillInfo需要一个我没有的对象(它只是一个模块级的函数),我尝试创建一个虚拟对象并传递给它,结果却导致了段错误,所以我猜这个对象应该以某种方式支持缓冲区……但是这个文档在哪里呢?

通过对内存视图的实验,我发现它们看起来和行为都不像字符串(或字节),所以我要么得重写所有的Python代码,要么想办法重新创建那种功能。

我是不是漏掉了什么?在Python 3中有没有简单的方法来替代PyBuffer_FromMemory?

注意:我在使用Cython,但这都是原生的C API内容,所以你可以不涉及Cython来回答。

2 个回答

0

听起来你应该创建一个自己的自定义类型,并在tp_as_sequence中实现一些方法(可能还需要在tp_as_buffer中实现)。

1

根据这个讨论,PyBuffer_FillInfo的第二个参数是可选的。你可以用NULL代替它吗?如果不行的话,你可以自己创建一个PyBuffer实例,然后填充相应的字段。

撰写回答