【问题标题】:Wrapping C++ code with python (manually)用 python 包装 C++ 代码(手动)
【发布时间】:2017-04-13 08:26:02
【问题描述】:

我有一个主文件(main.cpp)和一个头文件(nodes.hpp)。主文件将 N(任何正整数)作为输入参数,并通过使用头文件的函数给出输出 'x & y'(均为双精度)。

注意:

  1. 主文件和头文件都是用 C++ 编写的。
  2. 主文件和头文件都使用 Eigen 库,而不是使用数据结构作为数组、向量。

我必须为他们编写一个 python 包装器,我有 python 的工作知识,但从未使用过任何包装器。

任何人都可以参考或提供一些关于使用 python wrpper 编写此类代码的说明吗?

【问题讨论】:

  • 也许从 reading the documentation 开始,其中还提到了一些您可以调查的第三方工具。
  • 最好和最现代的库之一是pybind11(它每天都在变得越来越流行)。没有太多经验,除了 cython 之外,这是我尝试过的唯一一个,而且效果很好。与 SWIG 和 co 等重物相比,Boost.Python 通常被认为很好用。但它受到boost的构建工具的限制。如果您能够使用现代 c++ 编译器,这就是 pybind11 摆脱的!

标签: python c++ wrapper


【解决方案1】:

以下是您的选择:

  1. 您可以使用ctypes,我认为这是最干净的解决方案,因为您可以将程序转换为任何其他软件都可以调用的共享库,而不仅仅是 Python。但是,您必须自己为您的程序编写一个 C 接口。

  2. 您可以使用Python C-Extension,我认为这是最糟糕的解决方案,因为它的级别非常低,容易发生内存泄漏,并且需要大量时间来实现一个功能,并且依赖于 Python 版本。基本上,这是在 C++ 中启动 Python 解释器的好方法。您可以创建 PyObjects(这是任何 Python 类型的主要构建块)并在 C/C++ 中处理它们。

  3. 您可以使用SWIG,它会通过您定义的接口文件自动创建您必须使用 ctypes 创建的接口。人家说很好,但是文档没有那么好。

  4. 您可以使用Boost.Python,这很好,但它的构建系统非常丑陋,带有 bjam。如果你能设法绕过它,那么它甚至比 ctypes 更好。我是 boost 的忠实粉丝,但 bjam 是我不使用它的原因。

我通常做的是 ctypes。我相信它,因为它强调了single-reponsibility principle。该库有一个独立于接口(C 接口)的工作,它也与使用该接口并向用户公开“简单功能”的 Python 脚本分开。

【讨论】:

    【解决方案2】:

    使用 Boost.Python。这是我之前在 SO Docs 上的教程。


    使用 Boost.Python

    当您必须在 Python 项目中使用 C++ 库时,事情就变得简单了。只要你可以使用 Boost。

    首先这里是您需要的组件列表:

    • 一个 CMakeList.txt 文件,因为您将使用 CMake。
    • C++ 项目的 C++ 文件。
    • python 文件 - 这是您的 python 项目。

    让我们从一个小的 C++ 文件开始。我们的 C++ 项目只有一个方法返回一些字符串“这是第一次尝试”。称之为CppProject.cpp

    char const *firstMethod() {
        return "This is the first try.";
    }
    
    BOOST_PYTHON_MODULE(CppProject) {
        boost::python::def("getTryString", firstMethod); // boost::python is the namespace
    }
    

    在下面有一个 CMakeLists.txt 文件:

    cmake_minimum_required(VERSION 2.8.3)
    FIND_PACKAGE(PythonInterp)
    FIND_PACKAGE(PythonLibs)
    FIND_PACKAGE(Boost COMPONENTS python)
    
    INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
    
    PYTHON_ADD_MODULE(NativeLib CppProject)
    FILE(COPY MyProject.py DESTINATION .) # See the whole tutorial to understand this line
    

    通过本教程的这一部分,一切都变得如此简单。你可以在你的python项目中导入库和调用方法。调用你的 python 项目 MyProject.py

    import NativeLib
    print (NativeLib.getTryString)
    

    为了运行您的项目,请按照以下说明操作:

    • 创建一个名为 build 的目录。
    • 进入该目录。
    • 下达命令cmake -DCMAKE_BUILD_TYPE=Release ..
    • make
    • python MyProject.py。现在,您必须查看 C++ 项目中的方法返回的字符串。

    【讨论】:

    • 缺少#include boost/python.hpp
    • 非常感谢金枪鱼。那么,包装 C++ 代码实际上是在 Python 中编写相同的功能,还是在 Python 中运行 C++?这是否意味着我们需要 C++ 编译器来运行 Python 中的包装 C++ 代码?
    【解决方案3】:

    用官方文档试试:

    https://docs.python.org/2/extending/extending.html

    此链接将为您提供如何包含 cpp 模块并从 python 解释器中使用它的简单示例,或者如果可以尝试使用 Cython:http://cython.org/

    Cython 将允许您编写类似 C、类似 Python 的代码,这些代码将被翻译成 CPP 编译,然后可以从 Python 轻松访问。

    【讨论】:

      【解决方案4】:

      另一个用于生成 C++ 包装器的工具是 CLIF。谷歌于 2017 年发布,如今几乎所有事情都使用它。我们不再允许在内部为 Python 编写新的 SWIG 包装器。

      它构建在 Clang 之上,用于 C++ 解析,需要使用相对惯用的现代 C++ API(不出所料地遵循 Google's Style Guide),而不是任何试图让您通过 SWIG 的“支持一切都很糟糕”的方法来打自己的脚.

      【讨论】:

        【解决方案5】:

        您可以使用Boost.Python

        或使用 Python native interface

        如果您已经设置了 Boost,我会推荐 Boost.Python。

        【讨论】:

          猜你喜欢
          • 2012-06-14
          • 2011-11-15
          • 2020-09-13
          • 2017-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-24
          相关资源
          最近更新 更多