python调用C++

安装pybind11

为了使用C++ 编写python的扩展程序,参见[1],这里要介绍的是使用pybind11[3], pybind11使用比较简单,文档也比较详细。

本人的开发/测试环境为:

  • Ubuntu 18.04
  • pybind11
  • Anaconda3, with python 3.6
  • cmake

pybind11下载https://github.com/pybind/pybind11

下载好后,进入该目录进行安装:

mkdir build
cd build
cmake ..
make check -j 4

最后目录里的文件如下:

cpp+python

简单的例子:example.cpp

#include <pybind11/pybind11.h>

int add(int i, int j) {
    return i + j;
}

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

    m.def("add", &add, "A function which adds two numbers");
}

编译:

c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix`

 会生成一个.so文件 example.cpython-36m-x86_64-linux-gnu.so

添加python环境变量:当前.so文件所在路径,这样python就能使用这个模块了

export PYTHONPATH=$PYTHONPATH:/home/lzhr/workspace/libface

运行:

接下来,将其改成参数支持numpy,可参考官网文档pybind11—python numpy与C++数据传递

#include<iostream>
#include<pybind11/pybind11.h>
#include<pybind11/numpy.h>

namespace py = pybind11;

/*
1d矩阵相加
*/
py::array_t<double> add_arrays_1d(py::array_t<double>& input1, py::array_t<double>& input2) {

    // 获取input1, input2的信息
    py::buffer_info buf1 = input1.request();
    py::buffer_info buf2 = input2.request();

    if (buf1.ndim !=1 || buf2.ndim !=1)
    {
        throw std::runtime_error("Number of dimensions must be one");
    }

    if (buf1.size !=buf2.size)
    {
        throw std::runtime_error("Input shape must match");
    }

    //申请空间
    auto result = py::array_t<double>(buf1.size);
    py::buffer_info buf3 = result.request();

    //获取numpy.ndarray 数据指针
    double* ptr1 = (double*)buf1.ptr;
    double* ptr2 = (double*)buf2.ptr;
    double* ptr3 = (double*)buf3.ptr;

    //指针访问numpy.ndarray
    for (int i = 0; i < buf1.shape[0]; i++)
    {
        ptr3[i] = ptr1[i] + ptr2[i];
    }

    return result;

}


PYBIND11_MODULE(example, m) {
    m.doc() = "Simple demo using numpy!";
    m.def("add_arrays_1d", &add_arrays_1d);
}

执行同样的编译命令,然后python测试:

cmake编译pybind11

如果是用CMake编译的话,pybind11文件夹拷贝到/home/lzhr/workspace/libface/pydemo目录下,和example.cpp代码同级。

CMakeLists.txt如下:

cmake_minimum_required(VERSION 2.8.12)
project(example)

add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)

执行命令:

cmake .
make

编译成功后,添加下PYTHONPATH,就可以调用了

 

 

 

【参考】

[1] 如何实现 C/C++ 与 Python 的通信?

https://www.zhihu.com/question/23003213

[2] python 调用c++处理数组和图片

https://blog.youkuaiyun.com/koibiki/article/details/89478458

[3] pybind11官网介绍

https://pybind11.readthedocs.io/en/stable/basics.html

[4] pybind11—opencv图像处理(numpy数据交换)

https://www.jianshu.com/p/be16847b0b74

[5] pybind11—目标跟踪demo(深度学习人脸检测跟踪)

https://www.jianshu.com/p/5dc844002d72

[6] 混合编程[python+cpp+cuda]

[7] boost python3依赖安装

Python调用C++代码可以通过多种方法实现,主要包括使用扩展模块、C/C++接口封装以及工具链辅助生成绑定代码等方式。以下是几种常见且实用的方案: ### 1. 使用 `ctypes` 调用 C 风格共享库 虽然 `ctypes` 主要用于调用 C 编写的动态链接库(如 `.so` 或 `.dll`),但可以通过将 C++ 代码编译为具有 `extern "C"` 导出符号的共享库来间接调用 C++ 函数。 ```cpp // hello.cpp #include <iostream> extern "C" { void greet() { std::cout << "Hello from C++!" << std::endl; } } ``` 编译为共享库: ```bash g++ -shared -fPIC -o libhello.so hello.cpp ``` 然后在 Python调用: ```python import ctypes lib = ctypes.CDLL('./libhello.so') lib.greet() ``` ### 2. 使用 `Boost.Python` 创建 Python 扩展 `Boost.Python` 是一个功能强大的库,允许你直接将 C++ 类和函数暴露给 Python。它需要安装 Boost 库并进行适当的配置。 ```cpp // example.cpp #include <boost/python.hpp> char const* greet() { return "Hello from C++ with Boost.Python!"; } BOOST_PYTHON_MODULE(example) { using namespace boost::python; def("greet", greet); } ``` 编译命令示例: ```bash g++ -I/usr/include/python3.8 -I/usr/local/include/boost -fPIC -shared example.cpp -o example.so -lboost_python38 -lpython3.8 ``` 然后在 Python 中导入并使用: ```python import example print(example.greet()) ``` ### 3. 使用 `pybind11` 构建轻量级绑定 `pybind11` 是一个现代、轻量级的头文件库,专为简化 C++Python 的交互而设计,推荐用于新项目。 ```cpp // main.cpp #include <pybind11/pybind11.h> int add(int i, int j) { return i + j; } PYBIND11_MODULE(example, m) { m.def("add", &add, "A function that adds two numbers"); } ``` 编译命令(确保已安装 pybind11): ```bash c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) main.cpp -o example$(python3-config --extension-suffix) ``` Python 中使用: ```python import example print(example.add(3, 4)) # 输出 7 ``` ### 4. 使用 SWIG 自动生成绑定代码 SWIG 是一个自动包装器生成工具,支持多种语言,包括 PythonC++。适用于已有大型 C++ 项目希望快速暴露接口给 Python 的场景。 假设有一个 `example.i` 接口定义文件: ```swig %module example %{ #include "example.h" %} int add(int a, int b); ``` 对应的 `example.h` 和 `example.cpp` 实现了 `add` 函数。使用 SWIG 生成绑定代码后,再编译为 Python 模块即可调用。 --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值