如何从 C++ 调用 Python?
来自文档:
cppyy 是一个自动的运行时 Python-C++ 绑定生成器,用于 从 Python 调用 C++ 以及从 C++ 调用 Python。
(强调我的)
但是,我没有看到任何执行相同操作的说明,那么是否可以使用 cppyy 通过 C++ 调用 Python?
From the docs :
cppyy is an automatic, run-time, Python-C++ bindings generator, for
calling C++ from Python and Python from C++.
(Emphasis mine)
I don't see any instructions for doing the same, however, so is it possible to call Python via C++ using cppyy
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
作为限定符,由于我不知道您从哪里获得 cppyy,因此当时键入该句子的主要代码并不存在于 cppyy master 中,但确实存在于其历史悠久的 PyROOT 中。这个所谓的“类生成器”插件允许 Cling 将 Python 类“视为”C++ 类,以便直接回调,甚至从 Python 类继承 C++ 类。请参阅此出版物(第 3 页)了解一些示例: https://www.researchgate.net/publication/288021806_Python_in_the_Cling_World
此代码未移植到 cppyy 独立 b/c 类生成器依赖于交互式使用(特别是动态作用域),因此只能在 Cling 中工作,不能在编译代码中工作,并且(目前)还没有办法从 Python 进入 Cling 提示符(反之亦然)。
即使没有类生成器,这句话仍然存在的原因是 cppyy 此后发展了多种从 C++ 调用 Python 的其他方法(这些方法已向后移植到 PyROOT 中)。示例包括 C 样式函数指针、C++
std::function
对象、lambda 和跨语言继承。此外,这些都可以通过将 cppyy 导入嵌入式 Python 来使用(因此可以从编译的 C++ 中使用)。请参阅文档中的以下示例: 回调 和 交叉继承。交叉继承可能是最容易使用的:只需定义一个抽象接口,在 Python 中实现它,将指针传递给 C++,然后像使用 C++ 中的任何指向接口的指针一样使用它。对于回调,在标头中声明一个外部函数指针(或 std::function 对象),将其传递到嵌入式 Python 中的 cppyy.include 中,将 Python 函数分配给该指针,然后根据需要在 C++ 中调用它。
回调可以变得相当复杂,假设 C++ 端可以处理它。例如,通过在Python端提供注解,Python函数可以实例化C++函数指针模板。采用下面 C++ 中的完全通用回调,它接受任何参数并产生任何结果:
从 C++ 调用 Python 的最终方法确实没有记录,因为它(仍然)仅适用于 CPython/cppyy,不适用于 PyPy/_cppyy并且命名也是特定于实现的: CPyCppyy/API.h。
该标头旨在包含在 C++ 代码中,允许对 C++ 中的 cppyy 绑定实例进行装箱和拆箱、自定义转换器和执行器、内存管理以及存根函数的参数打包。还有一些方便的功能可以处理一次性问题。例如:(
虽然为了方便起见,这里的示例是从 Python 运行的,但这也可以从编译的 C++ 中的嵌入式 Python 调用)。
As a qualifier, since I don't know from where you obtained cppyy, the main code that was at the time the reason for typing that sentence does not exist in cppyy master, but does exist in its historic home of PyROOT. This so-called "class generator" plugin allows Cling to "see" Python classes as C++ classes, for straightforward callbacks and even inheritance of C++ classes from Python ones. See this publication (page 3) for some examples: https://www.researchgate.net/publication/288021806_Python_in_the_Cling_World
This code was not ported over to cppyy standalone b/c the class generator relies on interactive use (specifically, dynamic scopes), so only works from Cling, not compiled code, and there is no way (yet) to drop into the Cling prompt from Python (vice versa works).
The reason why that sentence is still there even without the class generator, is that cppyy has since grown a multitude of other ways to call Python from C++ (these have been backported into PyROOT). Examples include C-style function pointers, C++
std::function<>
objects, lambdas, and cross-language inheritance. Moreover, these can all be used by importing cppyy into embedded Python (and thus be used from compiled C++).See e.g. these examples in the documentation: callbacks and cross-inheritance. Cross-inheritance is probably the easiest to use: just define an abstract interface, implement it in Python, pass the pointer to C++ and use it like you would with any pointer-to-interface in C++. For callbacks, declare an extern function pointer (or
std::function
object) in a header, pass that in acppyy.include
in embedded Python, assign a Python function to that pointer, then call it in C++ as desired.Callbacks can be made quite sophisticated, assuming that the C++ side can handle it. For example, by providing annotations on the Python side, Python functions can instantiate C++ function pointer templates. Take the completely generic callback in C++ below, which accepts any arguments and producing any result:
The final way of calling from C++ into Python is indeed not documented b/c it is (still) only available for CPython/cppyy, not PyPy/_cppyy and the naming is implementation-specific as well: CPyCppyy/API.h.
This header is meant to be included in C++ code, allowing the boxing and unboxing of cppyy-bound instances from C++, custom converters and executors, memory management, and parameter packing for stub functions. There are also a couple of convenience functions for dealing with one-offs. For example:
(although the example here is run from Python for convenience, this can all be called from embedded Python in compiled C++ as well).
我不知道它是否回答了你的问题(从你的标题我知道你想从c++端调用python函数,但后来你似乎特别询问cpppy) 但您可以使用 pybind11。这个包被大量使用,并且在很多情况下被用作 swig< /a> (要了解差异,请查看 TensorFlow 社区中的这个开放线程)。这是 Python-C++ 绑定中最常用的两个包。
要了解如何在 Pybind11 中使用 C++ 调用 python 函数,请查看此问题,同时了解如何调用用于 swig 的 C++ 中的 python 函数看看 这个问题。
I do not know if it answer to your question (from your title I understand that you want to call python function from c++ side, but later it seems you ask specifically about 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 in the TensorFlow community). These are the two most used packages for Python-C++ binding.
To see how to call a python function in C++ for Pybind11 have a look at this question, while to see how to call a python function in C++ for swig have a look at this question.