如何从 C++ 调用 Python?

How to call Python from C++?

来自文档:

cppyy is an automatic, run-time, Python-C++ bindings generator, for calling C++ from Python and Python from C++.

(强调我的)

但是,我没有看到任何关于执行相同操作的说明,所以是否可以使用 cppyy 通过 C++ 调用 Python?

我很确定 cppyy 只允许您通过 Python 调用 C++,反之则不行。您可以使用 Python.h,或使用 C++ 来执行 python 文件,就像执行 .exe 文件一样,但这需要计算机可以 运行 python 文件。

作为限定词,由于我不知道你是从哪里得到cppyy的,所以当时输入这句话的主要代码在cppyy master中不存在,但存在于它的历史之家PyROOT。这个 so-called “class 生成器”插件允许 Cling 将 Python classes 视为 C++ classes,用于直接回调甚至继承 C++ classes 来自 Python 个。有关示例,请参阅此出版物(第 3 页):https://www.researchgate.net/publication/288021806_Python_in_the_Cling_World

此代码未移植到独立的 cppyy b/c class 生成器依赖于交互式使用(特别是动态范围),因此仅适用于 Cling,不适用于编译代码,并且有无法(还)从 Python 进入 Cling 提示(反之亦然)。

即使没有 class 生成器,那句话仍然存在的原因是 cppyy 从那以后发展了许多其他从 C++ 调用 Python 的方法(这些已经被移植到 PyROOT 中).示例包括 C-style 函数指针、C++ std::function<> object、lambda 和 cross-language 继承。此外,这些都可以通过将 cppyy 导入嵌入式 Python 来使用(因此可以从编译的 C++ 中使用)。

参见例如文档中的这些示例:callbacks and cross-inheritance。 Cross-inheritance 可能是最容易使用的:只需定义一个抽象接口,在 Python 中实现它,将指针传递给 C++ 并像在 C++ 中使用任何 pointer-to-interface 一样使用它。对于回调,在 header 中声明一个外部函数指针(或 std::function object),在嵌入式 Python 中的 cppyy.include 中传递它,分配一个 Python 指向该指针的函数,然后根据需要在 C++ 中调用它。

回调可以做得非常复杂,假设 C++ 端可以处理它。例如,通过在 Python 端提供注释,Python 函数可以实例化 C++ 函数指针模板。下面以 C++ 中的完全通用回调为例,它接受任何参数并产生任何结果:

>>> import cppyy
>>> cppyy.cppdef("""\
... template<typename R, typename... U, typename... A>
... R callT(R(*f)(U...), A&&... a) {
...    return f(a...);
... }""")
True
>>> def f(a: 'int') -> 'double':
...     return 3.1415*a
...
>>> cppyy.gbl.callT(f, 2)
6.283
>>> def f(a: 'int', b: 'int') -> 'int':
...     return 3*a*b
...
>>> cppyy.gbl.callT(f, 6, 7)
126
>>>

从 C++ 调用 Python 的最终方法确实没有记录 b/c 它(仍然)仅适用于 CPython/cppyy,不适用于 PyPy/_cppyy 和命名也是 implementation-specific:CPyCppyy/API.h.

此 header 旨在包含在 C++ 代码中,允许对来自 C++ 的 cppyy-bound 实例进行装箱和拆箱、自定义转换器和执行程序、内存管理以及存根函数的参数打包。还有一些处理 one-offs 的便利函数。例如:

import cppyy

def pyfunc():
    return 42

cppyy.cppdef("""\
#include "CPyCppyy/API.h"

int cppfunc() {
    return (int)CPyCppyy::Eval("pyfunc()");
}""")

print(cppyy.gbl.cppfunc())

(虽然这里的例子是 运行 来自 Python 为了方便,这也可以从嵌入式 Python 在编译的 C++ 中调用)。

我不知道它是否回答了你的问题(从你的标题我了解到你想从 c++ 端调用 python 函数,但后来你似乎专门询问了 cpppy) but you can do the binding with pybind11. This package is heavily used and is being used in a lot of case as an alternative to swig (to understand the differences have a look at this open thread TensorFlow 社区)。这是 Python-C++ 绑定最常用的两个包。

要了解如何在 C++ 中为 Pybind11 调用 python 函数,请查看 this question, while to see how to call a python function in C++ for swig have a look at this question