如何使用 cppyy 嵌入 Python 而不是 boost-python

How to use cppyy to embed Python instead of boost-python

我目前正在使用 boost-python 将 Python 解释器嵌入到我的 C++ 应用程序中,并促进将数据从已执行的 Python 进程传递到 运行 C++根据 https://www.boost.org/doc/libs/1_75_0/libs/python/doc/html/tutorial/tutorial/embedding.html

通过 boost-python 绑定应用

我在性能方面遇到了一些麻烦,尤其是在调用带有大量参数的包装函数时,解析和装箱所有这些参数以“传递”到 C++“端”的开销是相当大的。

我检查了 boost-python 的替代方案,例如 pybind11, which can also be embedded, but the performance is unlikely to improve. I also found out about cppyy,但是从文档中我不知道如何促进将解释器嵌入到我的程序中,或者更确切地说,我应该如何将我当前的嵌入式解释器方法转换为能够使用 cppyy。我尝试 cppyy 的目的是检查使用 cppyy and/or PyPy 作为解释器是否可以提高我的代码的性能,因为 boost-python 和 pybind11 都不支持嵌入 PyPy.

任何人都可以提供有关如何使用 boost-python 和 cppyy 替换嵌入式 Python 解释器的任何指示吗?

cppyy 嵌入接口尚未记录在案,因为它在 PyPy/cppyy 上不起作用(这似乎是您最具体要求的),仅适用于 CPython。对于后者,我不一定看到 whether/how 它会比 boost.python 或 pybind11 更快,因为它仍然依赖于装箱变量和 C-API 调用 Python.潜在地,C++ 类型查找更快,但仅此而已。

您可以通过从 cppyy 从 C++ (Cling) 调用 Python 并查看它的外观来轻松地使用它来获得一些性能数据。这是一个简单的例子:

import cppyy
import time

N = 10000000

def pycall(a):
    return a

cppyy.cppdef("""\
int (*ptr)(int) = 0;
void func(uint64_t N) {
    for (uint64_t i = 0; i < N; ++i)
        ptr(1);
}""")

cppyy.gbl.ptr = pycall

ts = time.perf_counter()
cppyy.gbl.func(N)
print('time per call:', (time.perf_counter()-ts)/N)

要使用您自己的代码和类型,而不是 int,只需将 headers 包含在 cppyy.include 中,并使用 cppyy.load_library() 加载库。 C++ 端的 Cling 和 Python 端的 cppyy 都将具有完全访问权限,因此您可以在回调中使用类型。

如果数字看起来更好,您需要的主要部分在 CPyCppyy/API.h 中,请参见此处:https://github.com/wlav/CPyCppyy/blob/master/include/CPyCppyy/API.h

目前我最好的建议是 CFFI,它只是 C 语言,但会为您提供可以直接使用并且在 PyPy 上对 JIT 友好的回调: https://cffi.readthedocs.io/en/latest/embedding.html