我需要用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版本。有人可以对此有所了解吗?
答案 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