【问题标题】:Generate python bindings, what methods/programs to use [closed]生成python绑定,使用什么方法/程序[关闭]
【发布时间】:2012-12-21 12:35:39
【问题描述】:

我正在考虑在我的程序中使用 python (CPython) 来允许在我的环境中编写用户脚本,并允许我使用 pyside(c++ 的 qt 绑定)为我的应用程序创建 GUI。这些可以有效地分开,因为 GUI python 代码以后可以编译掉以提高速度(如果可能的话)。

我对 python 很陌生,我真的在寻找最有效的方法来生成可靠的绑定,并且需要维护的附加代码绝对最少,因为绑定可能会随着项目的发展而经常变化。我需要它以便 python 类扩展具有虚拟的 c++ 类。

您在这方面推荐的任何帮助/建议/链接/工作流程都会非常有帮助。

【问题讨论】:

  • 恕我直言,如果您集成到该级别,那么您的 Python 和 C++ 部分很容易相互交织在一起。但总的来说,我支持寻求好的绑定。 +1。

标签: c++ python python-bindings


【解决方案1】:

我知道只有两个项目有 C++ 的自动绑定生成器。第一个是 SWIG。正如其他一些答案已经说过的那样,它有点过时,但它确实有效。第二个是 Boost.Python - 它本身不会自动生成绑定,但您可以使用 Boost.Pyste 为您完成。它需要 GCC-XML 来解析您的原始源代码并编写 Boost.Python 绑定。这两个选项都支持可以从 Python 重载的 C++ 中的虚拟方法。

也就是说,我必须补充一点,通常情况下,当你绑定时,你不会盲目地将 C++ 中的所有内容绑定到 Python 中——如果你这样做,你不会从 Python 中获得非常 Python 的感觉边。相反,你设计你希望你的库如何在 Python 中使用,以最 Pythonic 的方式,然后你回过头来看看如何使用可能的绑定库之一将它修补到你的 C++ 代码。例如,与其处理std::vector's,不如让您的库调用处理Python 列表或可迭代对象。如果您的 C++ 库收到 std::map,您希望使用 Python 字典来处理它。如果它是一个数组,也许numpy.ndarray 会更方便。等等……

也就是说,您仍然可以设计绑定,从而最大限度地减少维护。

以下是其他 Python/C++ 包装的列表,以防您决定进一步查看:

  1. SWIG - 你已经知道了
  2. Boost.Python - 这是我们通常在这里使用的 - 结构很好
  3. Cython - 非常简洁的语法接近 Python - 他们声称比 Boost.Python 快得多
  4. SIP - 传播的不多,但确实存在
  5. pybind11 - 类似于 Boost.Python 的语法,得益于 C++11 的紧凑实现。

这些现在处于非活动状态:

  1. PyBindGen - 声称是最快的,但自 2017 年 5 月 21 日起处于非活动状态,2014 年的上一个版本 - 目前在 github 上维护 (https://github.com/gjcarneiro/pybindgen/releases)
  2. ECS:Python - inactive 自 2014 年 12 月 6 日 (v2.8) 起,移至 github (https://github.com/MarcusTomlinson/ECS-Python)
  3. PyCXX - 使 Python 扩展更容易编写的 C++ 工具 - 不活动? 最后一个版本是 2017 年 4 月 23 日的 v7.0.2
  4. CLIF - CLIF 为为各种语言创建 C++ 包装器生成器提供了一个通用基础 - 不活跃? repo 上没有太多活动(只有 14 次提交)

为了完整起见,还可以将编译后的 C 代码直接加载到 Python 中,而无需创建正式的绑定。您可以使用FFI 执行此操作 使用这两个 Python 模块中的任何一个:

  1. ctypes - 这是 Python 原生的,不需要安装外部模块。
  2. cffi - 这是一个新包,灵感来自 Lua JIT 上的等效设计。

【讨论】:

  • 这个列表的新成员是 pybind11 (github.com/wjakob/pybind11, pybind11.readthedocs.org/en/latest)。免责声明:我是作者。
  • @WenzelJakob 我认为您应该使用该信息添加一个新答案,并在该帖子的正文中包含免责声明。
  • 安德烈,如果您想考虑添加 Wenzel Jakob 建议的信息,请这样做(此答案的修订版 4)。
  • 拜托了,我的声望显然不够……
  • 你来了...我不知道如何进行更改,所以很混乱。现在已经到位。感谢路过!
【解决方案2】:

如果您正在寻找速度,我也肯定会投票给 Cython。据我所知,将 C++ 与 Python 连接的其他方法,与其他绑定工具相比,Cython 的维护/更新并没有那么繁重,就“工作流的流畅性”增益而言。 (Cythonized 代码认为它和纯 C 一样快,或者离那不远,这也使它非常有趣)。

无论如何,有几个很好的 API 用于将 python 代码与 C++ 连接(Boost.Python,...),但我认为所有这些都将导致需要直接在 C++ 源代码中公开方法(你们告诉如果我错了,或者不准确,请告诉我)。

另一方面,Cython 将使您能够将 C++ API(GUI 或其他任何东西...)与暴露源(所谓的 .pyx 扩展名)严格分开。最终的工作流程是:

C++ API => 编译为共享对象 => Cython 扩展(导入和公开 C++ 功能)=> 扩展编译 => 使用扩展(要添加到你的 python 路径的扩展)。

好消息是,您只需要维护 .pyx 文件池中与不断发展的 C++ 特性相关的变化部分(其中包括需要公开的特性)。一开始这是一种投资,但根据我的经验,一旦设置了这个工作流程,让整个工作变得复杂起来就很简单了。

现在关于您需要扩展具有虚拟对象的类并从 Python 覆盖它们(如果我理解正确的话)。这是可行的。再一次,不是那么直接,但你应该看看这个thread

坏消息:在这种特殊情况下,您必须创建一些额外的 C++ 适配器/接口,以便在扩展的 python 没有覆盖给定父方法的情况下启用父方法的调用。 (请注意,从 python 重新定义 C++ 公开的方法,无论是否是虚拟的,都是对函数的替换,但绝对不等同于覆盖)。

Hummf,现在我正在回读自己,看起来有点混乱。希望这仍然有帮助。

如果您要求我选择 Cython 选项,我可以更具体地说明您必须处理的工作流程,但我认为上面链接的线程是一个很好的起点......

【讨论】:

  • 如果您需要有关使用 Cython 包装 C/C++ 库的更多详细信息,您可能还会发现我写的一篇有用的帖子 - 它包含包装和分发 C/C++ 库所需的所有详细信息:martinsosic.com/development/2016/02/08/…
【解决方案3】:

对于现代 C++,请使用 CLIF (https://github.com/google/clif)。 它不会发现你的 API,你需要用 Python 术语来描述它。

CLIF 将使用最新的 LLVM/Clang 编译器重新编译您的标头,并为 Python 扩展模块生成 C++ 源代码。

可以理解复杂的数据结构:def f() -> dict<str, set<int>>

【讨论】:

    【解决方案4】:

    对于现代 C++,使用 cppyy:http://cppyy.readthedocs.io/en/latest/

    它基于 Cling,Clang/LLVM 的 C++ 解释器。绑定在运行时,不需要额外的中间语言。感谢 Clang,它支持 C++17。

    针对使用 Qt 的原始问题:最近进行了几项更新以明确支持所有 KDE 的绑定生成。

    为了速度:PyPy 原生支持 cppyy。

    注意:我是cppyy的主要作者。

    【讨论】:

    【解决方案5】:

    AFAICT,C++ 的选择并不多。较老的项目之一是SWIG;据报道它有点神秘和笨重,但由于它已经存在了很长时间,它也应该涵盖很多其他项目没有处理的东西。您可能还想查看Cython

    【讨论】:

      【解决方案6】:

      SWIG 是一个很棒的工具,可以做你想做的事

      http://sourceforge.net/projects/swig/

      【讨论】:

        猜你喜欢
        • 2014-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-12
        • 2010-09-20
        • 2010-09-11
        • 2013-11-14
        相关资源
        最近更新 更多