项目篇:加入Python程序之如何在Python中使用C++?

项目篇:加速Python程序之如何在Python中使用C++?

通常像一些耗时的操作,我们期望在C++中去实现,然后使用Python去调用对应的接口,或者因为底层库的原因,需要支持对外的Python API,那么我们通常需要支持在Python中访问C++,如何实现呢?

方法比较多,本节以pybind11为例,引入一个完整的项目工程模版,如果你后续有这种需求,可以基于模版去修改。

注:(懒人版)本节的所有代码也都放在星球里面。

1.宏展开

假设:我们以比较耗时的排序为例,如果我们想在C++中写一个排序,然后在Python中去使用它,怎么去写呢?

C++程序是比较简单的,对外暴露一个接口里面做排序即可,例如:

std::vector<int> sort_vector(const std::vector<int>& input) {
  std::vector<int> result = input;
  std::sort(result.begin(), result.end());
  return result;
}

那么问题来了,对于Pybind11来说,如何使用这个接口呢?

使用pybind11的宏即可定义一个模块,例如:

PYBIND11_MODULE(sort_module, m) {
    m.doc() = "pybind11 example plugin"; // Optional module docstring

    m.def("sort_vector", &sort_vector, "A function that sorts a list of integers");
}

宏展开之后是:PyInit_sort_module

当我们在python当中import xxx库的时候,Python 解释器会去加载一个 C/C++ 编写的扩展模块时自动调用的入口函数,而这个入口函数就是下面的PyInit_sort_module:

static ::pybind11::module_::module_def pybind11_module_def_sort_module [[maybe_unused]];

[[maybe_unused]] static void pybind11_init_sort_module(::pybind11::module_ &);

extern "C" [[maybe_unused]] __attribute__((visibility("default"))) PyObject *PyInit_sort_module();

extern "C" __attribute__((visibility("default"))) PyObject *PyInit_sort_module() {
    {
        const char *compiled_ver = "3" "." "11";
        const char *runtime_ver = Py_GetVersion();
        size_t len = std::strlen(compiled_ver);

        if (std::strncmp(runtime_ver, compiled_ver, len) != 0 || (runtime_ver[len] >= '0' && runtime_ver[len] <= '9')) {
            PyErr_Format(PyExc_ImportError,
                         "Python version mismatch: module was compiled for Python %s, "
                         "but the interpreter version is incompatible: %s.",
                         compiled_ver, runtime_ver);
            return nullptr;
        }
    }

    pybind11::detail::get_internals();
    auto m = ::pybind11::module_::create_extension_module("sort_module", nullptr, &pybind11_module_def_sort_module);

    try {
        pybind11_init_sort_module(m);
        return m.ptr();
    } catch (pybind11::error_already_set & e) {
        pybind11::raise_from(e, PyExc_ImportError, "initialization failed");
        return nullptr;
    } catch (const std::exception &e) {
        ::pybind11::set_error(PyExc_ImportError, e.what());
        return nullptr;
    }
}

void pybind11_init_sort_module(::pybind11::module_ & m) {
    m.doc() = "pybind11 example plugin";

    m.def("sort_vector", &sort_vector, "A function that sorts a list of integers");
}

所以,如果我们不去使用这个宏,在import库的时候会报错:

>>> import sort_module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define module export function (PyInit_sort_module)

2.CMake + pybind11

pybind11在C++中的使用如下:

  • 头文件

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
PYBIND11_MODULE(sort_module, m) {
 // 你的实现
}

那么如何在cmake中下载并链接pybind11呢?

只需要使用FetchContent模块即可,例如:

FetchContent_Declare(
    pybind11
    URL https://github.com/pybind/pybind11/archive/v2.12.0.tar.gz
    )

然后在CMakeLists中加入你的模块即可:

pybind11_add_module(sort_module sort_module.cc)

cmake将会帮你下载pybingd11,同时编译好。

3.使用

上面会生成一个so,install到python的site-packages目录,然后import的时候便会识别,如下演示我们自定义的模块:

import sort_module

def test_sort():
    input_list = [5, 2, 3, 1, 4]
    sorted_list = sort_module.sort_vector(input_list)
    print(f"Original list: {input_list}")
    print(f"Sorted list: {sorted_list}")

if __name__ == "__main__":
    test_sort()

运行:

(base) ➜  build python ../test.py
Original list: [5, 2, 3, 1, 4]
Sorted list: [1, 2, 3, 4, 5]

93149002d8dba9e975cf47266addb33f.png

玩转cpp小项目星球3周年了!

fd5678de2b032d95b09c6de7855e4e0a.jpeg

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Boost::Python可以非常方便地实现C++调用Python接口。以下是简单的步骤: 1. 安装Boost库和Python解释器。 2. 编写一个Python模块,在其定义一些函数或类,这些函数或类是你希望C++调用的接口。 3. 用Boost::Python库将Python模块导出到C++,使得C++可以调用Python模块的函数和类。 4. 在C++代码调用Python模块的函数或类。 下面是一个简单的示例代码,演示了如何使用Boost::Python实现C++调用Python接口: ```cpp #include <boost/python.hpp> #include <iostream> // 定义一个Python函数 int add(int x, int y) { return x + y; } // 导出Python函数到C++ BOOST_PYTHON_MODULE(example) { using namespace boost::python; def("add", add); } int main() { // 初始化Python解释器 Py_Initialize(); // 导入Python模块 boost::python::object example_module = boost::python::import("example"); // 调用Python函数 boost::python::object result = example_module.attr("add")(1, 2); // 将Python返回值转换为C++类型 int sum = boost::python::extract<int>(result); // 输出结果 std::cout << "1 + 2 = " << sum << std::endl; // 释放Python解释器 Py_Finalize(); } ``` 在这个例子,我们定义了一个名为`add`的Python函数,在C++通过`def`函数将其导出。然后,在C++代码导入了Python模块,调用了Python函数,并将其返回值转换为C++类型。最后输出了结果。 这只是一个简单的例子,Boost::Python还支持更复杂的数据类型和类的导出。如果你想深入了解Boost::Python使用,可以参考官方文档和示例代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值