【问题标题】:Integrate Python And C++集成 Python 和 C++
【发布时间】:2010-11-12 07:40:51
【问题描述】:

我正在学习 C++,因为它是一种非常灵活的语言。但对于 Twitter、Facebook、Delicious 等互联网事物,Python 似乎是一个更好的解决方案。

是否可以在同一个项目中集成 C++ 和 Python?

【问题讨论】:

  • Boost.Python。使用两种语言的精华!
  • 请澄清“整合”是什么意思?运行在运行时生成或选择的 python 脚本的 C++ 程序?一个调用 c++ 例程的 python 脚本?来自两种语言来源的单个二进制文件?

标签: c++ python integration


【解决方案1】:

将 Python 与 C/C++ 交互并不是一件容易的事。

在这里,我在上一个问题上复制/粘贴 previous answer,以了解编写 python 扩展的不同方法。采用 Boost.Python、SWIG、Pybindgen...

  • 您可以使用 Python C-API 自己用 C 或 C++ 编写扩展。

    一句话:除了学习如何做之外,不要这样做。正确地做到这一点非常困难。您将不得不手动增加和减少引用,并编写大量代码只是为了公开一个函数,而好处很少。

  • Swig:

    专业人士:您可以为多种脚本语言生成绑定。

    缺点:我不喜欢解析器的工作方式。我不知道他们是否取得了一些进展,但两年前 C++ 解析器非常有限。大多数时候我不得不复制/粘贴我的 .h 标头来添加一些 % 字符并为 swig 解析器提供额外的提示。

    我还需要不时处理 Python C-API 以进行(不是那么)复杂的类型转换。

    我不再使用它了。

  • Boost.Python:

    专业人士: 这是一个非常完整的图书馆。它允许您使用 C-API 做几乎所有可能的事情,但在 C++ 中。我从来不需要用这个库编写 C-API 代码。由于库,我也从未遇到过错误。绑定代码要么像魅力一样工作,要么拒绝编译。

    如果您已经有一些 C++ 库要绑定,它可能是目前可用的最佳解决方案之一。但如果你只有一个小的 C 函数要重写,我可能会尝试使用 Cython。

    缺点:如果您没有预编译的 Boost.Python 库,您将使用 Bjam(类似于 make 的替代品)。我真的很讨厌 Bjam 及其语法。

    使用 B.P 创建的 Python 库往往会变得肥胖。编译它们也需要很多时间。

  • Py++:让 Boost.Python 变得简单。 Py++ 使用 C++ 解析器来读取您的代码,然后自动生成 Boost.Python 代码。您也得到了作者的大力支持(不,不是我 ;-))。

    缺点:只有 Boost.Python 本身的问题。

    编辑此项目看起来已停产。虽然可能仍在工作,但考虑切换可能会更好。

  • Pybindgen:

    它生成处理 C-API 的代码。你可以在 Python 文件中描述函数和类,或者让 Pybindgen 读取你的头文件并自动生成绑定(为此它使用 pygccxml,一个由 Py++ 的作者编写的 Python 库)。

    缺点:这是一个年轻的项目,团队比 Boost.Python 小。仍然有一些限制:不能公开自己的 C++ 异常,不能对 C++ 类使用多重继承。

    无论如何都值得一试!

  • 耐热玻璃和Cython

    这里你写的不是真正的 C/C++,而是 Python 和 C 的混合体。这个中间代码将生成一个常规的 Python 模块。

2013 年 7 月 22 日编辑: 现在 Py++ 看起来已停产,我现在正在寻找一个好的替代方案。我目前正在为我的 C++ 库尝试 Cython。这种语言是 Python 和 C 的混合体。在 Cython 函数中,您可以使用 Python 或 C/C++ 实体(函数、变量、对象……)。

Cython 非常容易学习,性能非常好,如果您不必连接旧版 C++ 库,您甚至可以完全避免使用 C/C++。

但是对于 C++,它会带来一些问题。它不像 Py++ 那样“自动化”,所以对于稳定的 C++ API(现在我的库就是这种情况)可能更好。我在 Cython 中看到的最大问题是 C++ 多态性。使用 Py++/boost:python 我能够在 C++ 中定义一个虚拟方法,在 Python 中覆盖它,并在 C++ 中调用 Python 版本。使用 Cython 仍然可行,但您需要明确使用 C-Python API。

编辑 2017-10-06:

有一个新的,pybind11,类似于 Boost.Python,但有一些潜在的优势。例如,它使用 C++11 语言特性来简化创建新绑定的过程。而且它是一个只有头文件的库,所以在使用它之前不需要编译,也不需要链接。

我用它玩了一下,它确实非常简单易用。我唯一担心的是,像 Boot.Python 一样,它可能会导致编译时间过长和库很大。我还没有做任何基准测试。

【讨论】:

  • 请注意,您指向 Py++ 的链接不再有效。我想他们搬到了这里:ohloh.net/p/pygccxml
  • @ZoranPavlovic:确实 Py++ 看起来已停产,我更新了链接。谢谢
  • 您应该添加用于 PySide 的 Shiboken。可怕的记录,但很棒。
  • 仅供参考:pybind11 文档包含有关编译时间和代码大小的基准 (pybind11.readthedocs.org/en/latest/benchmark.html)
  • @ascobol 你知道什么好的(易于使用)非开源库吗?
【解决方案2】:

是的,这是可能的,鼓励和documented。我自己做过,发现很简单。

【讨论】:

  • 感谢您的经验和非常好的文档!
  • 你向 Python 公开了多少个函数/类来轻松完成这项任务?
  • @ascobol:你很快就掌握了窍门。
  • 嗨,我去看了文档。需要包含哪些库才能调用 Python 函数?我从哪里获得Python.h
【解决方案3】:

Python/C API Reference Manual - 供想要编写扩展模块或嵌入 Python 的 C 和 C++ 程序员使用的 API。

Extending and Embedding the Python Interpreter

描述了如何用 C 或 C++ 编写模块以使用新模块扩展 Python 解释器。这些模块可以定义新功能,也可以定义新的对象类型及其方法。该文档还描述了如何将 Python 解释器嵌入到另一个应用程序中,以用作扩展语言。最后,它展示了如何编译和链接扩展模块,以便它们可以动态(在运行时)加载到解释器中,如果底层操作系统支持此功能。

【讨论】:

    【解决方案4】:

    试试Pyrex。使为 Python 编写 C++ 扩展变得更加容易。

    【讨论】:

    • Cython 是 Pyrex 的继承者。 (留下评论以帮助那些在 2014 年访问此答案的人)
    • 我认为将 Cython 称为 Pyrex 的一个分支会更准确。几年来,Pyrex 和 Cython 一直在同步发展。请注意,此时 Pyrex 不再处于积极开发中,因此不是新开发的理想选择。
    【解决方案5】:

    我们在产品中非常成功地使用了swig

    swig 基本上会获取您的 C++ 代码并围绕它生成一个 python 包装器。

    【讨论】:

      【解决方案6】:

      我建议看看 PyTorch 如何进行集成。

      【讨论】:

      • 为了节省下一个人的点击次数和谷歌,他们使用cffi 并有干净、简单的custom utilsrepo with examples 关于如何使用他们的实用程序来扩展pytorch。
      【解决方案7】:

      看这个:

      用 C 或 C++ 扩展 Python

      “如果您知道如何用 C 编程,那么向 Python 添加新的内置模块非常容易。这样的扩展模块可以做两件 Python 无法直接完成的事情:它们可以实现新的内置模块——在对象类型中,它们可以调用C库函数和系统调用。

      为了支持扩展,Python API(应用程序程序员接口)定义了一组函数、宏和变量,提供对 Python 运行时系统大部分方面的访问。 Python API 通过包含头文件“Python.h”被合并到 C 源文件中。 "

      http://www.python.org/doc/2.5.2/ext/intro.html

      PS 拼写为“整合”:)

      【讨论】:

        【解决方案8】:

        我过去使用过 PyCxx http://cxx.sourceforge.net/,我发现它非常好。

        它以非常优雅的方式包装了 python c API,并使其非常易于使用。 用 c++ 编写 python 扩展非常容易。它提供了清晰的示例,因此很容易上手。

        我真的很喜欢使用这个库,我强烈推荐它。

        【讨论】:

          【解决方案9】:

          这取决于您的便携性要求。我已经为此苦苦挣扎了一段时间,最后我直接使用python API 包装了我的 C++,因为我需要一些可以在管理员只将大部分工作的 gcc 和 python 安装一起破解的系统上工作的东西。

          理论上 Boost.Python 应该是一个很好的选择,因为 Boost(几乎)无处不在。不幸的是,如果您最终在一个具有较旧 default python 安装的操作系统上(我们的合作停留在 2.4),如果您尝试使用较新版本运行 Boost.Python,您将遇到问题(我们都使用 Python 2.6)。由于您的管理员可能不会费心安装与每个 python 版本相对应的 Boost 版本,因此您必须自己构建它。

          因此,如果您不介意在运行代码的每个系统上都需要一些 Boost 设置,请使用 Boost.Python。如果您想要的代码绝对可以在任何带有 Python 和 C++ 编译器的系统上运行,请使用 Python API。

          【讨论】:

            【解决方案10】:

            另一个有趣的方法是通过运行 python 本身来解析 c++ 头文件来生成 python 代码。 OpenCV team successfully took this approach 现在他们已经做了完全相同的事情来为 OpenCV 库制作 java 包装器。我发现这创建了更干净的 Python API,不受某个库的限制。

            【讨论】:

              【解决方案11】:

              您可以用 C++ 编写Python extensions。基本上 Python 本身是用 C 编写的,您可以使用它来调用您的 C 代码。您可以完全访问您的 Python 对象。另请查看Boost.Python

              【讨论】:

              • 还可以查看 OttoA 发布的文档:docs.python.org/extending/extending.html
              • Python != CPython。 CPython 是用 C 编写的。C != C++。
              • Python 是用 C 而不是 C++ 编写的。这就是为什么如果您使用 Python C-API,许多不错的 C++ 功能(如自动引用计数)必须手动完成。
              【解决方案12】:

              【讨论】:

                猜你喜欢
                • 2017-04-05
                • 2019-02-22
                • 2019-07-10
                • 2021-02-17
                • 2011-12-10
                • 2010-12-19
                • 1970-01-01
                • 2011-11-25
                • 2012-03-23
                相关资源
                最近更新 更多