使用pybind11实现矩阵加法(实现CMake编译C++生成.pyd(python库文件))
主要涉及流程:
- pybind11包下载并使用CMake编译
- Eigen包下载
- 利用Visual Stdio新建CMake工程
- 修改其中的.cpp文件和.h文件中的相关内容
- 修改CMakeLists.txt文件中的内容
- 编译CMake工程文件,生成.pyd文件
- 编写测试代码,调用.pyd文件
1.pybind11包下载
pybind11是一个轻量级的只包含头文件的库,它主要是用来在已有的 C++代码的基础上做扩展,它的语法和目标非常像Boost.Python,但Boost.Python为了兼容现有的基本所有的C++编译器而变得非常复杂和庞大,而因此付出的代价是很多晦涩的模板技巧以及很多不必要的对旧版编译器的支持。Pybind11摒弃了这些支持,它只支持python2.7以上以及C++ 11以上的编译器,使得它比Boost.Python更加简洁高效。
Github下载地址:https://github.com/pybind/pybind11
在CMa构建CMake工程之前,我们需要安装Pytest,这里采用pip安装:
pip install pytest
在安装完成后,我们使用CMD定位到pybind目录文件夹下,使用CMake编译pybind,依次执行以下语句: 在这里为了防止产生的文件较乱,将新建一个build文件夹,将所有编译后的文件夹都存放入build文件夹。
mkdir build
cd build
cmake ..
会在build文件中生成工程文件。 在这里需要去学习一下pybind11,学习地址:
https://pybind11.readthedocs.io/en/stable/
其中涉及一些必要的知识点。
2.Eigen包下载(该包会在矩阵计算时会调用到)
Eigen是可以用来进行线性代数、矩阵、向量操作等运算的C++库,它里面包含了很多算法。它的License是MPL2。它支持多平台。
Eigen采用源码的方式提供给用户使用,在使用时只需要包含Eigen的头文件即可进行使用。之所以采用这种方式,是因为Eigen采用模板方式实现,由于模板函数不支持分离编译,所以只能提供源码而不是动态库的方式供用户使用。
Eigen包下载地址:
https://eigen.tuxfamily.org/index.php?title=Main_Page
3.利用Visual Stdio新建CMake工程
打开Visual Stdio >文件>新建>项目>选择CMake项目,之后命名项目名,保存到指定位置即可。
新建完成后,将上面一二步的pybind11文件和Eigen文件复制到新建的CMake文件中。为了方便调用其内部函数。
4.修改其中的.cpp文件和.h文件中的相关内容
同时新建一个与工程名相同的.cpp文件与.h文件
在.h文件中可以写入你将要导入的包,在.cpp文件中写入将要执行的.cpp代码。
下面讲一些注意事项:
1、在编写.cpp程序时必须要导入的库:
#include "pybind11/pybind11.h"
#include "pybind11/eigen.h"
#include "eigen/Core"
#include "eigen/Dense"
其中(#include “pybind11/eigen.h”)为关键,其中涉及到python中numpy库函数的调用,如果未加这条代码,可能会报错。
2、在导入库后,必须添加的最下面两条代码
using namespace std;
namespace py = pybind11;
using namespace Eigen;
3、之后可以自己编写自己想要实现功能的函数(注意是函数,应为方便后期生成.pyd文件并调用.pyd文件)
MatrixXd Matrix_addition_end(MatrixXd a, MatrixXd b) {
if (a.cols() == b.cols() && a.rows() == b.rows()) {
return a + b;
}
else {
cout << "输入矩阵行列不一" << endl;
}
}
4、设立PYBIND11_MODULE函数,这个也较为重要,PYBIND11_MODULE第一个参数设定为与项目名称相同,其中在m.def函数中,需要将前两项参数里的内容设置为自己所定义的函数名。
PYBIND11_MODULE(Matrix_addition, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring
m.def("Matrix_addition_end", &Matrix_addition_end, "A前两项设置为与 function which adds a matrix");
}
5、修改CMakeLists.txt文件中的内容
1、修改project,将project中的参数设置为自己的工程名
project (Matrix_addition)
2、添加需要包含的子项目(文件夹)
# 包含子项目。
add_subdirectory (pybind11)
include_directories("C:/Users/pc/source/repos/Matrix_addition/eigen")
add_subdirectory (eigen)
3、添加工程需要导入的模型
pybind11_add_module(Matrix_addition Matrix_addition.cpp)
6、编译CMake工程文件,生成.pyd文件
1、首先通过CMD命名,到工程的目录文件夹下,执行如步骤1中相同的操作和代码;
2、在执行完CMake …后,能够在build文件夹中找到与工程名相同的.sln文件
双击打开后,在解决方案资源管理器中鼠标右击ALL BUILD点击生成。
就会在build文件中生成一个Debug文件夹,生成的.pyd文件就在这里。
将它复制出来,利用import调用即可。
7、以下展示实现矩阵加法各个文件的代码以及实验测试代码:
重要文件
.cpp文件:
// Matrix_addition.cpp: 定义应用程序的入口点。
//
#include "Matrix_addition.h"
#include "pybind11/pybind11.h"
#include "pybind11/eigen.h"
#include "eigen/Core"
#include "eigen/Dense"
using namespace std;
namespace py = pybind11;
using namespace Eigen;
MatrixXd Matrix_addition_end(MatrixXd a, MatrixXd b) {
if (a.cols() == b.cols() && a.rows() == b.rows()) {
return a + b;
}
else {
cout << "输入矩阵行列不一" << endl;
}
}
PYBIND11_MODULE(Matrix_addition, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring
m.def("Matrix_addition_end", &Matrix_addition_end, "A function which adds a matrix");
}
.h文件:
// Matrix_addition.h: 标准系统包含文件的包含文件
// 或项目特定的包含文件。
#pragma once
#include <iostream>
// TODO: 在此处引用程序需要的其他标头。
CMakeList.txt:
cmake_minimum_required (VERSION 3.8)
project (Matrix_addition)
add_subdirectory (pybind11)
include_directories("C:/Users/pc/source/repos/Matrix_addition/eigen")
add_subdirectory (eigen)
pybind11_add_module(Matrix_addition Matrix_addition.cpp)
测试代码:
import Matrix_addition as ma
import numpy as np
x = np.mat('1.1 0 0 ; 0 1.1 0 ; 0 0 1.1')
y = np.mat('0 1.1 1.1 ; 1.1 0 1.1 ; 1.1 1.1 0')
c=ma.Matrix_addition_end(x,y)
print(c)
注意:测试代码需要和.pyd文件放在一起,才能够调用函数。
|