使用带有嵌入式 PyPy 的外部“Python”样式 cffi 回调

Posted

技术标签:

【中文标题】使用带有嵌入式 PyPy 的外部“Python”样式 cffi 回调【英文标题】:Use extern "Python" style cffi callbacks with embedded PyPy 【发布时间】:2016-03-27 07:36:04 【问题描述】:

可以嵌入 PyPy 使用新的 extern "Python" 样式 cffi 回调吗? PyPy 的文档仅显示旧式 cffi 回调,但 cffi 文档建议不要使用它们。 PyPy 文档没有提及新样式回调,我无法让新样式回调工作。

Embedding PyPy

Extern “Python” (new-style callbacks)

# file "interface.py"

import cffi

# add new extern "Python" declaration
ffi = cffi.FFI() ffi.cdef('''
struct API 
    double (*add_numbers)(double x, double y);

    extern "Python" void add_numbers2(double, double);
; ''')

# Better define callbacks at module scope, it's important to
# keep this object alive.
@ffi.callback("double (double, double)")
def add_numbers(x, y):
    return x + y

# new function
@ffi.def_extern()
def add_numbers2(x, y):
    return x + y


def fill_api(ptr):
    global api
    api = ffi.cast("struct API*", ptr)
    api.add_numbers = add_numbers

运行编译后的 C 时出错(C 的源代码与 PyPy 文档相同):

debug: OperationError:
debug: operator-type: CDefError
debug: operator-value: cannot parse "extern "Python" void add_numbers2(double, double);"
:6:5: before: extern
Error calling pypy_execute_source_ptr!

【问题讨论】:

确实,我们需要查看嵌入文档。请注意,“embedding-using-extern-Python”的全部功能仍在开发中。同时,请注意在“struct API”中使用“extern Python”是没有意义的。 【参考方案1】:

“extern Python”实际上并不打算现在在您所指的嵌入情况中使用。为了更好地支持这种情况,cffi 的开发人员需要付出更多的努力(包括我 :-)。换句话说,未来的 cffi 版本应该提供一种替代方法来进行嵌入,比 CPython 和 PyPy 的自定义解决方案更简单(分别是“使用 CPython C API”和“遵循https://pypy.readthedocs.org/en/latest/embedding.html”)。它还应该提供一个单一的通用解决方案。但是,现在还没有完成。

您可以在 PyPy 文档的示例之上应用现有的 (cffi 1.4)“extern Python”解决方案,但它需要进行一些重构——值得注意的是,该示例使用“内联 ABI 模式”,而“extern Python”仅适用于“离线 API 模式”。如果我们认为https://pypy.readthedocs.org/en/latest/embedding.html 描述了一种纯粹的 ABI 模式方法,那么使用ffi.callback() 仍然是 CFFI 中记录的唯一方法。

更新: CFFI 1.5 完全支持“extern Python”样式的嵌入 (http://cffi.readthedocs.org/en/latest/embedding.html)。它现在可以在 CPython 上使用。 PyPy 需要主干版本(或 PyPy 4.1,应该在 2016 年 3 月或 4 月推出)。

【讨论】:

您好,很高兴有一位 cffi 开发人员经过。哦,我看到文档已经更新,谢谢!那么目前是否可以在 PyPy 嵌入中使用“extern Python”解决方案和“out-of-line API 模式”? 是的,使用 bpaste.net/show/ee8f2d365248 之类的东西(未经测试!)。手动运行一次_interface_build.py,制作_interface_cffi.so。 @ArminRigo 这个答案是否还反映了CFFI 1.5发布后的现状?

以上是关于使用带有嵌入式 PyPy 的外部“Python”样式 cffi 回调的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 cffi 在 C 中嵌入一个返回字符串的 Python 函数?

带有 debezium 嵌入式连接器的外部偏移存储

pypy真的能让python比c还快?

带有外部和嵌入式 yaml 的 RMarkdown

初步安装使用PyPy

Python 解释器 PyPy 7.3.3 版本发布!