Python调用C++函数之Pybind11

目录

Pybind11

如何在C++中使用Pybind11

1.将Pybind11加入到submodule中

2.编写C++程序

调用python接口


Pybind11

Pybind11 是一个轻量级的 C++ 库,用于将你的 C++ 代码暴露给 Python 调用(反之也可,但主要还是前者)。Pybind11 借鉴了 Boost::Python 库的设计,但使用了更为简洁的实现方式,使用了大量 C++11 的新特性,更易于使用。

如何在C++中使用Pybind11

1.将Pybind11加入到submodule中

添加子模块非常简单,命令如下:

git submodule add <url> <path>

其中,url为子模块的路径,path为该子模块存储的目录路径。example:

git submodule add https://github.com/pybind/pybind11.git third_party/pybind11

执行上述命令时,会从github上clone到你指定的<path>处,同时会在仓库生成.gitmodules文件,该文件会记录添加的submodule的url和存放submodule的路径,如下:

2.编写C++程序

本例中,我们实现了一个快排的C++类,类的定义如下:

#include <common.h>

class SortFactory
{
public:
    void setData(std::vector<int> &raw_data)
    {
        data_ = raw_data;
    }
    std::vector<int> &getData()
    {
        return data_;
    }
    void printData(std::vector<int> &sorted_data)
    {
        for (auto item : sorted_data)
        {
            std::cout << item << " ";
        }
        std::cout << std::endl;
    }
    virtual void sort(){};

private:
    std::vector<int> data_;
};

class QuickSort : public SortFactory
{
public:
    QuickSort() {};
    void sort1(std::vector<int> &data);
    void mySort(int start, int end, std::vector<int> &data);
};

类的实现如下:

#include <sort/sort.h>

//{3,2,4,5,7,8,0}
//{0,2,4,5,7,8,3}
void QuickSort::mySort(int start, int end, std::vector<int> &data)
{
    int tmp_start = start;
    int tmp_end = end;
    if (start >= end)
        return;
    int tmp = data[end];
    while (start < end)
    {
        while (data[start] <= tmp)
        {
            start++;
            if (start >= end)
                break;
        }

        data[end] = data[start];
        while (data[end] >= tmp)
        {
            if (start >= end)
                break;
            end--;
        }
        data[start] = data[end];
    }
    data[start] = tmp;
    mySort(tmp_start, start - 1, data);
    mySort(end + 1, tmp_end, data);
}

void QuickSort::sort1(std::vector<int> &data)
{
    int size = data.size();
    int start = 0;
    int end = size - 1;
    mySort(start, end, data);
    printData(data);
}

其中,QuickSort中的sort函数就是我们需要绑定的函数,目录结构如下:

pythonApi文件夹下,pythonSort是绑定QuickSort类中的sort函数的文件,定义如下:

#include <include/pybind11/pybind11.h>
#include <sort/sort.h>

namespace py = pybind11;

PYBIND11_MODULE(MyQuickSort, m)
{
    py::class_<QuickSort>(m, "QuickSort")
        .def(py::init())
        .def("sort", &QuickSort::sort1);
}

pythonSort对应的CMake文件,定义如下:

include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${PROJECT_SOURCE_DIR}/third_party/pybind11)
include_directories(${PROJECT_SOURCE_DIR}/third_party/pybind11/include)
include_directories(/usr/include/python3.8/)

message(${PROJECT_SOURCE_DIR})

add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/pybind11 pybind11_binary_dir)

add_library(MyQuickSort MODULE pythonSort.cpp)
target_link_libraries(MyQuickSort PRIVATE my_sort)

pybind11_extension(MyQuickSort)
pybind11_strip(MyQuickSort)

issue

在编译的时候遇到了一个问题,如下:

pybind11/include/pybind11/detail/../detail/common.h:274:10: fatal error: Python.h: No such file or directory
  274 | #include <Python.h>
      |          ^~~~~~~~~~
compilation terminated.

参考了如下的文章,执行sudo apt install python3.8-dev之后问题并没有解决,所以采用了笨办法,发现Python.h文件在/usr/include/python3.8下,所以直接在cmake文件中添加include_directories(/usr/include/python3.8/),此时问题解决了。

fatal error: Python.h: No such file or directory when compiling pybind11 example - Stack Overflow

Issues with running the first example · Issue #1781 · pybind/pybind11 · GitHub

调用python接口

在python中调用绑定的接口,此时需要export $PYTHONPATH=$PYTHONPATH:~/cmakestudy/build/src/pythonApi

import MyQuickSort

data = [1,3,4,2,90,23,4,5,78]
a = MyQuickSort.QuickSort()
a.sort(data)

此时可能会报一个错误,如下:

Invoked with: <MyQuickSort.QuickSort object at 0x7fb96ae01cb0>, [1, 3, 4, 2, 90, 23, 4, 5, 78]

Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,
<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic
conversions are optional and require extra headers to be included
when compiling your pybind11 module.

此时需要在pythonApi绑定函数中添加引用,如下:

#include <include/pybind11/pybind11.h>
// new add
#include <include/pybind11/stl.h>
#include <sort/sort.h>

namespace py = pybind11;

PYBIND11_MODULE(MyQuickSort, m)
{
    py::class_<QuickSort>(m, "QuickSort")
        .def(py::init())
        .def("sort", &QuickSort::sort1);
}

代码:https://github.com/xiaoycolor/cmakestudy/tree/main/src/pythonApi

参考:

pybind11 documentation

  • 29
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sirly。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值