0

我需要用 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: initializer for ctype 'char[]' must be a bytes or list or tuple, not 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 版本。有人可以对此有所了解吗?

4

2 回答 2

2

使用 Python3 运行此代码时,出现以下错误:TypeError: initializer for ctype 'char[]' must be a bytes or list or tuple, not str

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

AttributeError:“FFI”对象没有属性“set_source”

这意味着你有一个旧版本的 PyPy。CFFI 的版本不能在给定版本的 PyPy 中升级;你需要升级 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'

我很确定您使用的是旧版本的 PyPy,它带有旧版本的 CFFI,而不是 1.2.1。

于 2015-09-16T22:11:24.883 回答
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
于 2017-03-08T10:08:41.623 回答