Pybind11 将C++代码绑定Python

在科学计算和数据处理领域,Python以其简单易用和丰富的生态系统而闻名。然而,在性能方面,C++通常比Python更高效。为了充分发挥两种语言的优势,我们可以使用Pybind11将C++代码绑定到Python,从而在Python中调用C++代码,实现高性能和易用性的完美结合。

Pybind11是一个用于创建Python绑定的轻量级库,它使得将C++代码绑定到Python非常简单。在本文中,我们将演示如何使用Pybind11将简单的C++函数绑定到Python,并在Python中调用这些函数。

打开Clion 编写配置文件CMakeLists.txt

注意:如果在拓展中需要使用 opencv  需要自己编译。网上很多教程。

并且用visual studio 编译 opencv, 生成lib 文件

 

项目结构:

​​​​​​​

 

// example.cpp

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <Eigen/Dense>
#include <opencv2/opencv.hpp>


namespace py = pybind11;

int add(int a, int b) {
    return a + b;
}

py::list List(const py::list &l) {
    py::list li;
    for (int i = 0; i < l.size(); ++i)li.append(i);
    li.append("str");
    return li;
}

std::tuple<float, float> Tuple(float a, float b) {
//    return std::make_tuple(a, b);
    return {a, b};
}

std::tuple<double, double>
center(py::array_t<uint16_t> &np_arr) {

    py::buffer_info buf = np_arr.request();

    cv::Mat image(static_cast<int>(buf.shape[0]), static_cast<int>(buf.shape[1]),
                  CV_16UC1, (unsigned char *) buf.ptr);

    cv::Moments m = moments(image, true);
    double cx = m.m10 / m.m00;
    double cy = m.m01 / m.m00;

    return std::make_tuple(cx, cy);
}

std::tuple<Eigen::MatrixXd, double>
imageSun(Eigen::MatrixXd image, double energy = 1) {
    image.array() += energy;
    return std::make_tuple(image, image.sum());
}


PYBIND11_MODULE(example, m) {
    m.doc() = "python example";
    m.def("add", &add, "add 加法");
    m.def("List", &List, py::arg("l") = nullptr, "传入List 返回List");
    m.def("Tuple", &Tuple, py::arg("a"), py::arg("b"), "返回Tuple");
    m.def("center",
          &center,
          py::arg("image"),
          "returns(center_x center_y)");
    m.def("imageSun", &imageSun,
          py::arg("image"),
          py::arg("energy") = 1,// 默认参数=1
          "returns(numpy_arr sum)");

}

// exampleclass.cpp

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

// ------------------
// regular C++ header
// ------------------

// parent class
class Animal {
public:
    virtual std::string talk(int n_times) = 0;
};

// derived class
class Dog : public Animal {
public:
    std::string talk(int n_times) override;
};

// derived class
class Cat : public Animal {
public:
    std::string talk(int n_times) override;
};

// function that takes the parent and all derived classes
std::string talk(Animal &animal, int n_times = 1);

// ----------------
// regular C++ code
// ----------------

inline std::string Dog::talk(int n_times) {
    std::string result;

    for (int i = 0; i < n_times; ++i)
        result += "woof! ";

    return result;
}


inline std::string Cat::talk(int n_times) {
    std::string result;

    for (int i = 0; i < n_times; ++i)
        result += "meow! ";

    return result;
}


std::string talk(Animal &animal, int n_times) {
    return animal.talk(n_times);
}

// -----------------------------
// Python interface - trampoline
// -----------------------------

class PyAnimal : public Animal {
public:

    // inherit the constructors
    using Animal::Animal;

    // trampoline (one for each virtual function)
    std::string talk(int n_times) override {
        PYBIND11_OVERLOAD_PURE(
                std::string, /* Return type */
                Animal,      /* Parent class */
                talk,        /* Name of function in C++ (must match Python name) */
                n_times      /* Argument(s) */
        );
    }
};

// ----------------
// Python interface
// ----------------

namespace py = pybind11;

PYBIND11_MODULE(exampleclass, m) {
    py::class_<Animal, PyAnimal>(m, "Animal")
            .def(py::init<>())
            .def("talk", &Animal::talk);

    py::class_<Dog, Animal>(m, "Dog")
            .def(py::init<>());

    py::class_<Cat, Animal>(m, "Cat")
            .def(py::init<>());

    m.def("talk", &talk, py::arg("animal"), py::arg("n_times") = 1);
}

# python setup.py sdist bdist_wheel
from setuptools import setup, Extension

module1 = Extension(
    'PyExample.example',
    include_dirs=['D:/library/include'],
    sources=['PyExample/example.cpp'],
    extra_compile_args=['-std:c++17', '-Zc:__cplusplus', '-permissive-', '-utf-8'],
)

module2 = Extension(
    'PyExample.exampleclass',
    include_dirs=['D:/library/include'],
    sources=['PyExample/exampleclass.cpp'],
    library_dirs=['D:/library/lib'],
    libraries=['opencv_world480'],
    extra_compile_args=['-std:c++17', '-Zc:__cplusplus', '-permissive-', '-utf-8'],
)

setup(
    name='PyExample',
    version='0.1',
    packages=['PyExample'],
    ext_modules=[module1, module2],
)

编译:

python setup.py sdist bdist_wheel

 

 安装:

pip install Py***-0.0.0.tar.gz
或者
pip install Py***-0.0.0-cp311-cp311-win_amd64.whl

python 使用:

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值