流程说明 <big>python里调用C++代码主要分为编写c++代码、代码绑定、编译代码和调用四步,本demo主要说明这个流程,并着重讲述其中的代码绑定和编译代码 工程目录说明 .vscode文件夹是vsode建立工程所必须的文件夹 build是为编译脚本和cmake编译使用的文件夹 include是c++头文件夹 lib是库文件存放目录 src是c++源文件夹(类似于op实现存放的目录) ceshi.py是python调用c++的python文件 CMakeLists.txt是cmake编译所需文件 pybindsetup.py是pybind11编译源码的脚本 torchsetup.py是pytorch编译源码的脚本 test1.jpg是本demo所需图片</big>
setp1-编写C++代码(建议遵循C++编码规范)<big><b> bind.cpp为各种结构的绑定说明文件,不同结构绑定方式存在差异 classbind.cpp为类的一些复杂绑定方式说明文件 demo.cpp是一个python和C++互相传递消息的例子,python向C++传递一张图,c++保存,然后c++将保存的图传递给python pythonmapc.cpp是一个python的一些内置类型可以直接映射到pybind11内置类的说明文件 simple.cpp是一个简单的python调用C++的编写例子,python调用c++的函数</big>
step2-代码绑定python调用C++的代码,是通过注册机制,所以需要书写绑定代码,例子如下: <!-- bind是生成的库名,也是python调用的模块名,cmake生成的库名会带有lib,所以该名称应该加入lib前缀,如simple.cpp的中名称定义为libsimple
m.def("add", &add)是定义函数的绑定方式,add表示函数名,&add表示引用的c++函数 -->
#include<pybind11/pybind11.h>
PYBIND11_MODULE(bind, m){
m.def("add", &add);
}<big>说明: 其它结构的绑定代码参考bind.cpp文件,但应注意一个源文件只能有一个PYBIND11_MODULE定义。 bind.cpp中有多个PYBIND11_MODULE的定义只是为了方便阅读,所以源文件中注释掉了这部分。 torch框架下的绑定名称可以使用TORCH_EXTENSION_NAME。 当然可以将PYBIND11_MODULE中定义的m通过函数调用在别处进行代码绑定。例如:</big>
#include <pybind11/functional.h>
<!-- 源文件中声明 -->
void initBind(py::module_ &m); //c++规范,声明在前
<!--PYBIND11_MODULE中调用-->
initBind(m);
<!-- 源文件中书写 -->
void initBind(py::module_ &m){
//绑定代码
}setp3-编译代码<big>本demo中并存三种编译方式,下面对三种编译方式进行说明 cmake(建议喜欢cmake的人使用):对应CmakeLists.txt,适用于不在pytorch环境下 cmake的编写例子</big>
mkdir build & cd build
cmake ..
maketorchsetup.py:建议在pytorch的环境下使用,调用该脚本会自动生成编译指令和链接指令,该脚本其实是setuptools的extension和build_ext的封装,故参数与其一致,只不过会加上torch的头文件和库文件搜索路径以及torch所需的编译选项。 extension的参数说明
<!-- 使用方法 -->
<!-- 首先先修改该脚本所需的参数 -->
python torchsetup.py install <!-- 生成编译命令和链接命令的例子 -->
gcc -pthread -B /home/dongbo/anaconda3/envs/pt2/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/dongbo/pybind11_demo/include -I/usr/local/include/opencv4 -I/home/dongbo/anaconda3/envs/pt2/lib/python3.8/site-packages/torch/include -I/home/dongbo/anaconda3/envs/pt2/lib/python3.8/site-packages/torch/include/torch/csrc/api/include -I/home/dongbo/anaconda3/envs/pt2/lib/python3.8/site-packages/torch/include/TH -I/home/dongbo/anaconda3/envs/pt2/lib/python3.8/site-packages/torch/include/THC -I/home/dongbo/anaconda3/envs/pt2/include/python3.8 -c demo.cpp -o build/demo.o -shared -std=c++14 -DTORCH_API_INCLUDE_EXTENSION_H -DPYBIND11_COMPILER_TYPE=\"_gcc\" -DPYBIND11_STDLIB=\"_libstdcpp\" -DPYBIND11_BUILD_ABI=\"_cxxabi1011\" -DTORCH_EXTENSION_NAME=demo -D_GLIBCXX_USE_CXX11_ABI=1
g++ -pthread -B /home/dongbo/anaconda3/envs/pt2/compiler_compat -Wl,--sysroot=/ -pthread -shared -B /home/dongbo/anaconda3/envs/pt2/compiler_compat -L/home/dongbo/anaconda3/envs/pt2/lib -Wl,-rpath=/home/dongbo/anaconda3/envs/pt2/lib -Wl,--no-as-needed -Wl,--sysroot=/ build/demo.o -L/usr/local/lib -L/home/dongbo/anaconda3/envs/pt2/lib/python3.8/site-packages/torch/lib -Wl,--enable-new-dtags,-R/usr/local/lib -lopencv_imgcodecs -lc10 -ltorch -ltorch_cpu -ltorch_python -o build/demo.so说明:-I 是头文件搜索目录链接,为torchsetup.py中setup方法中的include_dirs包含的字段,没指定的字段由pytorch框架自己引入。-c 是torchsetup.py中setup方法中extra_compile_args包含的字段-shared -std=c++14是torchsetup.py中setup方法中包含的字段<big>特别需要注意编译器宏定义字段GLIBCXX_USE_CXX11_ABI,编译过程中该字段值的设置需与pytorch的torch.C._GLIBCXX_USE_CXX11_ABI一致,这涉及到c++的ABI互相兼容问题。 <!-- 使用方法 -->
<!-- 首先先修改该脚本所需的参数 -->
python pybindsetup.py install除此之外,还有本demo未包含的编译方式 参考链接。
setp4-方法调用在python端使用如下 import libsimple #由于torchsetup.py和pybindsetup.py会将包直接安装到环境中,故可直接引入;cmake默认库安装在本工程目录下也可直接引入(当然也可以指定安装路径)。
import demo
#import importlib
#module = importlib.import_module('name of the lib') #import的等效方法
#方法调用
libsimple.add(1, 2)
#类创建
b = bind.Dog('dd')
d.bark() # 非默认情况下如何引入包,保证该路径在环境中
import sys
sys.path.append("path/to/the root path of lib")
|