本文将用C++编写一个简单的向量运算库,然后使用pybind11将其封装为python包,再使用python调用。C++程序使用CMake构建。使用C++调用Python模块见:另一篇博客
安装pybind11
使用pybind11可以将使用C++11以上标准编写的函数、类或者lambda表达式封装为python包。
安装pytest
pip3 install pytest
下载pybind11
git clone https://github.com/pybind/pybind11.git
编译安装
cd pybind11
mkdir build
cd build
cmake ..
cmake --build . --config Release --target check
sudo make install
C++
创建cpp文件,命名为example.cpp
,在其中实现几个向量运算函数和类,并使用pybind11库将其封装成python包,包名为example
,内容如下:
#include <iostream>
#include <vector>
using std::vector;
// 向量内积,返回一个标量,输入的向量要等长
double inner_product(const vector<double>& vec1, const vector<double>& vec2){
double sum = 0;
for(int i = 0; i < vec1.size(); i++){
sum += vec1[i] * vec2[i];
}
return sum;
}
// 向量求和,返回一个向量
vector<double> sum(const vector<double>& vec1, const vector<double>& vec2){
auto result = vec1;
for(int i = 0; i < vec1.size(); i++){
result[i] += vec2[i];
}
return result;
}
// 定义一个向量类
class Vector{
public:
Vector()=default;
~Vector()=default;
以下重新实现了上述函数
double inner_product(const vector<double>& vec1, const vector<double>& vec2){
double sum = 0;
for(int i = 0; i < vec1.size(); i++){
sum += vec1[i] * vec2[i];
}
return sum;
}
vector<double> sum(const vector<double>& vec1, const vector<double>& vec2){
auto result = vec1;
for(int i = 0; i < vec1.size(); i++){
result[i] += vec2[i];
}
return result;
}
};
// 使用pybind11将以上函数和类封装为python包
#include <pybind11/pybind11.h>
#include <pybind11/stl.h> // 函数中用到了C++的STL库,所以要包含该头文件
PYBIND11_MODULE(example, m){
m.doc() = "my example";
// 封装函数
m.def("inner_product", &inner_product);
m.def("sum", &sum);
// 封装用lambda表达式表示的函数
// 以下函数用于输出指定字符串
m.def("print", [](std::string& str){
std::cout << str << std::endl;
});
// 封装类
pybind11::class_<Vector>(m, "Vector")
.def(pybind11::init())
.def("inner_product", &Vector::inner_product)
.def("sum", &Vector::sum);
}
CMakeLists.txt
内容如下:
cmake_minimum_required(VERSION 3.0.4)
project(example)
# 添加pybind11依赖
find_package(pybind11 REQUIRED)
message(STATUS "pybind11 version: ${pybind11_VERSION}")
# 添加pybind11头文件路径
include_directories(
${pybind11_INCLUDE_DIRS}
)
# 添加python包
pybind11_add_module(example src/example.cpp)
编译完成后,build
文件夹下将会出现example.cpython-3xm-x86_64-linux-gnu.so
类似文件,这就是编译生成的库,接下来编写python脚本来调用。
Python
# 添加C++库的路径
import sys
sys.path.append("/home/ubuntu/workspace/example_python_use_cpp/build")
import example
a = [3, 2, 1]
b = [2.1, 5, 2]
# 使用单独的函数
example.print("---- use single function -------")
example.print("a · b = " + str(example.inner_product(a, b)))
example.print("a + b = " + str(example.sum(a, b)))
# 使用类
example.print("---- use class -----------------")
vector = example.Vector() # 类实例化
example.print("a · b = " + str(vector.inner_product(a, b)))
example.print("a + b = " + str(vector.sum(a, b)))
运行结果如下:
---- use single function -------
a · b = 18.3
a + b = [5.1, 7.0, 3.0]
---- use class -----------------
a · b = 18.3
a + b = [5.1, 7.0, 3.0]