Python,PyPy和CFFI:我应该使用什么?

时间:2015-09-16 09:13:55

标签: python-3.x pypy python-cffi

我需要用python调用C库,经过一些考虑后,CFFI似乎最适合这种工作。然而,到现在为止,如果我正确使用它,我会感到很困惑,因为有些东西似乎只在PyPy上运行,而其他东西似乎只适用于Python3(就我所知,PyPy不支持它) )。

以下是CFFI文档中最基本的代码示例:

>>> from cffi import FFI
>>> ffi = FFI()
>>> ffi.cdef("""
...     int printf(const char *format, ...);   // copy-pasted from the man page
... """)
>>> C = ffi.dlopen(None)                     # loads the entire C namespace
>>> arg = ffi.new("char[]", "world")         # equivalent to C code: char arg[] = "world";
>>> C.printf("hi there, %s.\n", arg)         # call printf
hi there, world.
17                                           # this is the return value
>>>

使用Python3运行此代码时,出现以下错误:     TypeError:ctype'char []'的初始值设定项必须是字节或列表或元组,而不是str

寻找错误,我发现它是去年1月在PyPy中修复的一个问题。所以我看看这个东西是否与PyPy一起运行,而且确实如此。万岁!

然而,在第二个例子中,我正在反过来解决问题:

# file "simple_example_build.py"

# Note: this particular example fails before version 1.0.2
# because it combines variadic function and ABI level.

from cffi import FFI

ffi = FFI()
ffi.set_source("_simple_example", None)
ffi.cdef("""
    int printf(const char *format, ...);
""")

if __name__ == "__main__":
    ffi.compile()

在PyPy中运行它会引发另一个错误:

AttributeError: 'FFI' object has no attribute 'set_source'

由于该示例有助于它在旧版本上无效,我检查了我的CFFI版本:1.2.1,一切都没问题。

最后,我用Python3而不是PyPy运行第二个例子,谁会想到,它确实完成了它应该做的事情。

刚开始使用Python,到目前为止,我不再知道我应该使用什么,以及为什么同一文档中的示例只能在不同版本的语言上运行。当然还有一个问题,我可能只是配置了一些错误(对于Linux也是新的),或者我应该完全使用另一个python版本。有人可以对此有所了解吗?

2 个答案:

答案 0 :(得分:2)

  

当使用Python3运行此代码时,我收到以下错误:TypeError:ctype'char []'的初始化程序必须是字节或列表或元组,而不是str

是的,因为对于Python 3,您需要使用'b'前缀来确保处理字节。文档中的示例清楚地说明了这一点。

  

AttributeError:'FFI'对象没有属性'set_source'

这意味着你有一个旧版本的PyPy。在给定版本的PyPy中无法升级CFFI的版本;你需要升级PyPy本身。检查您的特定PyPy附带的CFFI版本如下:

$ pypy
Python 2.7.9 (295ee98b6928, May 31 2015, 07:29:04)
[PyPy 2.6.0 with GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>> import cffi
>>>> cffi.__version__
'1.1.0'

我很确定你使用的是旧版本的CFFI附带的旧版PyPy,而不是1.2.1。

答案 1 :(得分:0)

你可以修改如下:

from cffi import FFI
ffi = FFI()
ffi.cdef("""int printf(const char *format, ...);""")
C = ffi.dlopen(None)                     # loads the entire C namespace
arg = ffi.new("char[]", b"world")         # equivalent to C code: char arg[]     = "world";
C.printf(b"hi there, %s.\n", arg)         # call printf
相关问题