pybind11是用来进行C++和python互相调用的库。
用pybind11的动机就是再用python处理数据的时候很慢,但是又无法用GPU加速,网上找了一下发现了这个库,利用python调用C++的程序,处理速度能快不少,因此就决定探索一下。
但是作为一个编程菜鸡,对C++了解很少,一直用的python,所以走了很多弯路,花了好几天的工夫才弄成功。下面说一下我遇到的主要问题。
一、windows系统
1.pybind11安装
从GitHub上下载源码:点这里下载。
2.支持的C++软件
我用了一下visual studio2019,因为之前没用过,结果出各种问题,所以我就去vscode了,然后一直用vscode弄了半天也没成功,后来发现官网上说了,pybind11只支持visual studio2015之后的版本。。。。。
所以建议直接用visual studio
下载安装过程就不说了,一搜就搜到。
写一下配置项目过程。
先创建一个新项目
选择空项目,下一步
起名,选择位置,然后创建。
创建源文件
选择属性。
配置选择release,VC++目录这里包含anaconda的include目录和pubind11目录,如果包含pybind11.h头文件不成功的话,也可以采用将include文件中的pybind11文件夹复制到当前包含头文件的目录下的方法,就可以导入了。
库目录选择anacobda的Libs目录
然后是链接器设置。
vs2019设置好了,接下来就是pybind代码。
#include<pybind11/pybind11.h>
namespace py = pybind11;
PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example module";
// Add bindings here
m.def("foo", []() {
return "Hello, World!";
});
}
由于pybind11是head-only的,因此只需要导入头文件就可以了。
2.编译
代码写好之后,进行编译,这里我用的是CMake,下载过程不说了,网上搜就能搜到。
在解决方案目录下新建文件夹build,用于保存编译的内容。
新建CMakelists.txt文件,填写以下内容。
cmake_minimum_required(VERSION 2.8.12)
project(example)
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
这里语句含义不说了,戳这里查看CMakelists.txt的语句含义。
将下载的pybind11-master放到这里,重命名为pybind11。
因为这句话add_subdirectory(pybind11)意思是加子模块,将pybind11加到目录下,不然会出错。
用CMake编译时,上边那一行是源代码位置,也就是解决方案的目录,下边那行是编译后方的位置,选择build文件夹,然后点击configure,然后generate,应该不会出问题。
然后会在build中生成example.sln文件,这个是解决方案文件,双击打开。
点击生成。
结果成功,产生的pyd文件就是可以在python里导入的包。
然后查看一下自己的pycharm导入包的路径,随便导入一个包,然后Ctrl+鼠标左键点击查看。
这里是包的目录。
将pyd文件复制过来,注意:如果在pycharm里复制的话,他会产生一个同名文件夹,将这个文件包含在里边,但是这样导入不了,因此必须是以纯pyd文件的形式出现在site-packages里。
导入的时候example就是这个包,而不是文件全称,导入之后查看一下就知道是不是这个文件。
这说明导入的没错,接下来就是测试一下了。
C++源代码里定义了一个函数foo,打印输出,这里只需要直接调用就可以了。
或者在终端用命令行测试,也是一样的。
二、linux系统
1.安装pytest
pip install pytest
2.下载源码和新建文件
git clone https://github.com/pybind/pybind11.git
输入上边命令下载好pybind11的源码后,会在当前目录下出现一个pybind11目录,就是下载好的文件。
然后再当前目录下,也就是和pybind11同级目录下,建立c++文件example.cpp,内容如下:
#include <pybind11/pybind11.h>
namespace py = pybind11;
int add(int i, int j)
{
return i + j;
}
PYBIND11_MODULE(example, m)
{
// optional module docstring
m.doc() = "pybind11 example plugin";
// expose add function, and add keyword arguments and default arguments
m.def("add", &add, "A function which adds two numbers", py::arg("i")=1, py::arg("j")=2);
// exporting variables
m.attr("the_answer") = 42;
py::object world = py::cast("World");
m.attr("what") = world;
}
再在当前目录下建立文件CMakeLists.txt
内容如下:
cmake_minimum_required(VERSION 3.5.1)
project(example)
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
SET( CMAKE_CXX_FLAGS "-std=c++11 -O3")
也就是说pybind11和example.cpp以及CMakeLists.txt三个文件都是在同一个目录下。
3.编译
选择pybind11文件进入,进入之后建立build文件然后cmake,make,具体操作如下:
cd pybind11
mkdir build
cd build
cmake ..
make
每次输入一行命令然后回车。
输入完之后应该会成功编译,然后会在build下产生一个example******.so文件,名字很长记不全了,大概是长这样的,so文件就是linux系统下可以在python中导入的库,在Windows系统下是.pyd文件,在linux系统下是.so文件,然后参照windows系统上的方法把生成的.so文件放到python的库目录下,然后import example就可以正常使用了。
结束语:折腾了好久 好久,哎,这种东西对C++新手太不友好了!!之前用别人的代码里他们就用了pybind11了,那时折腾半天也没搞明白就放弃了开始自己写代码,写到最后发现,多重for循环的处理数据速度真是慢到令人发指,所以又开始了探索,幸好这次弄出来了,太激动了,写下了这一篇文章,这也是第一次写这么多字,费了我一个多小时,不过弄出来还是很激动的,22:07分,走了,回宿舍啦!