【问题标题】:How to implement a C interface in Python and pass objects using CFFI如何在 Python 中实现 C 接口并使用 CFFI 传递对象
【发布时间】:2021-06-06 08:11:32
【问题描述】:

我想知道如何使用现有的 C 接口(头文件)并使用 CFFI 库在 Python 中实现这样的接口。

例如我有如下头文件,interface.h:

void* foo(void* value);

我想在 Python 中实现它。我认为下面的程序可以完成这项工作,但事实并非如此。它创建函数foo,但不保证实现遵循头文件中定义的结构。

import cffi

ffibuilder = cffi.FFI()

with open('interface.h') as f:
    data = ''.join([line for line in f if not line.startswith('#')])
    ffibuilder.embedding_api(data)

ffibuilder.set_source("_lib", r'''
    #include "interface.h"
''')

ffibuilder.embedding_init_code("""
    from _lib import ffi

     #include "interface.h"

    @ffi.def_extern()
    def foo(param):
        return __import__(param)

""")

ffibuilder.compile(verbose=True)

如何使用 CFFI 传递 Python 对象?

在上面的示例中,作为调用 foo 的结果,返回一个 Python 对象。 然后在客户端,我有以下内容:

ffi = FFI()
# Load my lib file
lib = C.CDLL(dll)

h = lib.foo("math")

当我查找 h 的值时,它显示了一个整数类型的数字。但是,我期待收到一个对象。根据接口,foo必须返回一个指针void*。我怎样才能从中读取该对象?我做错了吗?

【问题讨论】:

  • 这对我来说是正确的。你到底在问什么?你能举一个你所说的失败的例子吗?
  • 例如,如果我将方法 foo 的实现更改为接收两个参数而不是一个。它仍然有效(我认为它不应该因为它与头文件的规范不匹配)。
  • “它仍然有效”,因为您可以运行上述脚本并编译 .so/.dll 文件,是的。就像如果函数在变量名中包含拼写错误一样,您可以编译它。它可以编译,但在运行时失败。如果这就是您所关心的,那么首先使用 Python 可能不是正确的选择...
  • 你是对的,@ArminRigo!谢谢!

标签: python c python-cffi cffi


【解决方案1】:

回答您的最后一个问题:在此示例中,您使用的是ctypes,而不是cffi。这些是不同的项目。这应该很明显,因为ffi 对象来自cffi,但在以下几行中未使用。而不是lib = C.CDLL() 我猜Cctypes 的别名,你应该打电话给lib = ffi.dlopen("...")

【讨论】:

  • 是的,你是对的。我使用ctypes 加载DLL 文件。但是,我尝试将其更改为ffi.dlopen,但是当我尝试调用库中的任何函数时它不起作用。这是输出错误:文件“/python_app.py”,第 65 行,在 print(py.foo(5)) 文件“/python_app.py”,第 51 行,在 fooz return self.lib.foo( bn) 文件“/venv/lib/python2.7/site-packages/cffi/api.py”,第 912 行,在 getattr make_accessor(name) 文件“/venv/lib/python2.7 /site-packages/cffi/api.py",第 907 行,在 make_accessor 中引发 AttributeError(name) AttributeError: foo
【解决方案2】:

我发现问题在于从 ctypes 切换到 CFFI 以加载 DLL 时。第一个需要定义动态库中可用的方法。 因此,添加它可以解决问题

ffi.cdef("""
  void foo(void* value);
""")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    相关资源
    最近更新 更多