文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何从 Python 调用C++

2023-09-06 17:31

关注

        Python是一种高级编程语言,它可以调用其他语言编写的函数。在 Python 中调用 C 函数的方法有两种:1)使用 Python 提供的 ctypes 库;2)使用 Python 提供的 Cython 库。

        注意:您可以在此存储库中下载此示例的完整代码。如果您对本文有任何意见,可以在那里开始一个问题,或与我联系

        基本上有两种方法可以从 Python 调用C++:使用 PyBind11 C++ 库生成 Python 模块,或者使用 cytpes Python 包访问编译的共享库。使用 PyBind11,我们可以更轻松地共享许多数据类型,而使用 ctypes 是一种低级的 C 样式解决方案

        就我而言,我希望能够利用C++性能和可移植性,但我不想放弃解释语言的交互性以进行快速探索和调试

        幸运的是,从Python调用C++并不像一开始看起来那么困难。这样,我们可以在开发C++代码的同时掌握 Python 的一些交互性。

就我而言,我想使用 Python 来:

        使用 ctypes 的问题在于,共享许多数据类型需要相当多的低级解决方法。例如,虽然ctypes不支持复数等基本的东西,但PyBind11使Numpy与Eigen完全互操作,需要最少的代码。

        但是,我也发现了 PyBind11 的小问题。事实证明,在重新编译C++代码并尝试重新加载 PyBind 生成的 Python 模块后,什么也没发生。重新加载编译模块的唯一方法是重新启动我的 Python 会话。无论如何,这没什么大不了的,因为Python的启动时间可以忽略不计。而且,此步骤可能在 IDE 级别自动执行。

        因此,现在的问题是如何充分利用 PyBind11。

        PyBind11 的官方文档非常出色,我可以毫无问题地开始使用它。但是,我想分享这个库的超级快速入门指南,以及我打算如何使用它。

        Pybind11 是一个仅标头库,你可以通过以下方式获取它:

 
pip install pybind11

        虽然没有必要将所有C++代码构建为一个类,但如果你有一个类要在C++和 Python 之间共享,Pybind11 会让你的事情变得非常容易。(其实我更像是那种人,总是想介绍给定项目中最少的类数)vectorstruct

        然而,在这种情况下,我发现使用外观设计模式(参见wiki)可以同时导致非常简单的Python/C++互操作性和一个不错的API。

        所以,我想出了一个简单的课程。它基本上包含:

        这是我的最小示例:

// mylib.h#include #include using Eigen::Matrix, Eigen::Dynamic;typedef Matrix, Eigen::Dynamic, Eigen::Dynamic> myMatrix;class MyClass {    int N;    double a;    double b;public:    Eigen::VectorXd v_data;    Eigen::VectorXd v_gamma;    MyClass(){}    MyClass( double a_in, double b_in, int N_in)     {        N = N_in;        a = a_in;        b = b_in;    }    void run()     {         v_data = Eigen::VectorXd::LinSpaced(N, a, b);         auto gammafunc = [](double it) { return std::tgamma(it); };        v_gamma = v_data.unaryExpr(gammafunc);    }};

        要共享这个类,我们需要添加一些C++代码。我宁愿在一个单独的文件中执行此操作,其中包含创建 python 包装器所需的一切。

 
// pywrap.cpp#include #include #include "mylib.h"namespace py = pybind11;constexpr auto byref = py::return_value_policy::reference_internal;PYBIND11_MODULE(MyLib, m) {    m.doc() = "optional module docstring";    py::class_(m, "MyClass")    .def(py::init())      .def("run", &MyClass::run, py::call_guard())    .def_readonly("v_data", &MyClass::v_data, byref)    .def_readonly("v_gamma", &MyClass::v_gamma, byref)    ;}

        需要强调的几点:

        最后,可以使用以下文件进行编译:CMakeLists.txt

 
cmake_minimum_required(VERSION 3.10)project(MyLib)set(CMAKE_CXX_STANDARD 20)set(PYBIND11_PYTHON_VERSION 3.6)set(CMAKE_CXX_FLAGS "-Wall -Wextra -fPIC")find_package(pybind11 REQUIRED)find_package(Eigen3 REQUIRED)pybind11_add_module(${PROJECT_NAME} pywrap.cpp)target_compile_definitions(${PROJECT_NAME} PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO})target_include_directories(${PROJECT_NAME} PRIVATE ${PYBIND11_INCLUDE_DIRS})target_link_libraries(${PROJECT_NAME} PRIVATE Eigen3::Eigen)

        现在你已经准备好了。如果您使用的是 VS Code,则在配置 CMake 扩展后,只需按 F7 即可编译C++库。

        这个过程非常简单,应该开箱即用。但是,有几个步骤可以优化交互式工作流,这些步骤稍微棘手一些,也值得实施。

        例如,如果您正在执行 Python 环境并且您的编译库进入一个目录,您可以执行以下操作:build

 
import syssys.path.append("build/")from MyLib import MyClassimport matplotlib.pyplot as pltSimulation = MyClass(-4,4,1000)Simulation.run()plt.plot(Simulation.v_data, Simulation.v_gamma, \"--", linewidth = 3, color=(1,0,0,0.6),label="Function Value")plt.ylim(-10,10)plt.xlabel("x")plt.ylabel("($f(x) = \gamma(x)$)")plt.title("(Gamma Function: $\gamma(z) = \int_0^\infty x^{z-1} e^{-x} dx$)",fontsize = 18);plt.show()

伽玛示例

        请注意,特征向量会自动转换为 Python 数组

        Ater 修改 ,每个我们要公开的新函数或变量只需要添加一行代码。myLib.hpppywrap.cpp

        不幸的是,这不会带来完全交互式的工作流程。当您在更改后重新编译C++代码时,Python 端不会发生任何事情。即使您尝试使用以下方法重新加载 Python 模块:importtools

 
import importlibimportlib.reload(MyLib)

        什么也没发生。原因是编译后的代码无法在 Python 中重新加载

        因此,在使用 PyBind11 时,每次重新编译C++代码时都需要重新启动 Python 会话,我觉得这对于开发目的来说有点烦人。但是,这是一个很小的代价,因为Python的启动时间可以忽略不计,并且可能有一种方法可以使用一些IDE热键或其他工具使该过程自动化。

        因此,这就是您可以轻松地从 Python 调用C++库的方式。

        特别是,这个两步过程可以产生一个非常互动的开发工作流程。尽管我们有一个编辑-编译-运行工作流,但我们在最后添加了一个解释器,所以现在我们的工作流看起来像编辑-编译-运行-探索。

        将来,我计划将两个功能合并到此工作流中:

来源地址:https://blog.csdn.net/gongdiwudu/article/details/131968528

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯