欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

[Pybind11] 为 Python 调用实现 C++ 接口(Windows 和 Ubuntu)

最编程 2024-07-15 09:13:48
...

Windows

1. 官网下载pybind11:https://github.com/pybind/pybind11/releases/tag/v2.3.0

2. VS新建空项目

  • 项目属性页—配置属性—常规—配置类型改为动态库(.dll)
    • 项目属性页—配置属性—高级—目标文件扩展名调整为 .pyd
    • 项目属性页—配置属性—VC++目录—包含目录:添加python和pybind的include路径
    • 我这里使用的是anconda全家桶    C:\ProgramData\Anaconda3\include    D:\software\pybind11-2.3.0\pybind11-2.3.0\include
    • 项目属性页——配置属性——VC++目录——库目录:添加python文件中的libs路径:C:\ProgramData\Anaconda3\libs
    • 项目属性页——配置属性——链接器——输入中添加python的lib: python37.lib   python3.lib

3. 代码示例:写好的c++代码以后,VS生成解决方法,在路径下生成一个.pyd文件,将pyd文件放入python路径下,或者import绝对路径:如import example

示例一:

(1)c++代码
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <vector>
using std::vector;
namespace py = pybind11;
vector<float> ListMul(vector<float>& in_list, float coef) 
{
    vector<float> ret_vec;
    ret_vec.clear();
    ret_vec.reserve(in_list.size()); 
    // Requests that the vector capacity be at least enough to contain n elements.
    for (size_t i = 0; i < in_list.size(); ++i) 
    {
        int v = in_list[i];
        ret_vec.push_back(coef * v);
    }
    return ret_vec;
}

PYBIND11_MODULE(example, m) 
{
    m.doc() = "pass and return a list";
    m.def("ListMul", &ListMul, "example function");
}
(2)python代码
import example
print(example.ListMul([1.0, 2, 3, 4, 5, 6], 5))

示例二:(传递numpy数组)

(1)c++代码
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
namespace py = pybind11;
py::array_t<double> add_arrays(py::array_t<double> input1, py::array_t<double> input2) 
{
 	// read input arrays buffer_info
     py::buffer_info buf1 = input1.request(), buf2 = input2.request();
    if (buf1.size != buf2.size)
 	    throw std::runtime_error("Input shapes must match");
 	// allocate the output buffer
 	py::array_t<double> result = py::array_t<double>(buf1.size);
 	py::buffer_info buf3 = result.request(); // acquire buffer info
 	double* ptr1 = (double*)buf1.ptr, * ptr2 = (double*)buf2.ptr, * ptr3 = (double*)buf3.ptr;
    size_t high = buf1.shape[0];
 	size_t width = buf1.shape[1];
     // Add both arrays
 	for (size_t idy = 0; idy < high; idy++)
    {
 		for (size_t idx = 0; idx < width; idx++)
 			{
   				int curIdx = idy * width + idx;
  				ptr3[curIdx] = ptr1[curIdx] + ptr2[curIdx];
  			}
 	}
 /* Reshape result to have same shape as input */
 result.resize({ high, width });
 return result;
}

PYBIND11_MODULE(example, m) 
{
    m.doc() = "Add two vectors using pybind11"; // optional module docstring
    m.def("add_arrays", &add_arrays, "Add two NumPy arrays");
}
(2)python调用代码
import numpy as np
import example
a = np.ones((10,3))
b = np.ones((10,3)) * 3
c = example.add_arrays(a, b)
print(c)

Ubuntu

1. 安装pytest:Sudo pip3 install pyptest

2. git clone https://github.com/pybind/pybind11.git

3. 进入pybind11目录

cd pybind11

mkdir build

cd build

camke ..

make -j8

sudo install

4. 将使用pybind格式编写好的c++代码放入pybind的同一目录下

5. 编辑makefile进行编译

CXXFLAGS = -I include  -std=c++11 -O3 $(shell python3-config --cflags)
LDFLAGS = $(shell python3-config --ldflags)
CXX_SOURCES = example.cpp
LIB_SO = example.so
$(LIB_SO): $(CXX_SOURCES) $(DEPS)
    $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $(CXX_SOURCES) --shared -fPIC
clean:
    rm -rf $(LIB_SO)
注意,其中具体编译命令前不允许有空格,使用tap

6. sudo make , 生成example.so

参考博客:

https://blog.****.net/qq_27009517/article/details/106466655

https://www.jb51.net/article/164588.htm

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

https://blog.****.net/u013701860/article/details/86305680

推荐阅读