C++/Python联合编译:pybind11
Python方便但效率低,C++效率高但不方便,那不如把他们合起来用?
本篇介绍Python作为API、C++作为底层实现的方式之一:pybind11.
想要联合编译Python和C++有很多种方法和工具,我目前在用的是pybind11,给我感觉挺方便好用的。
安装pybind11
对于Linux来说,如果官方源里面有的话,可以直接从官方源安装,如:
1 | $ sudo pacman -S pybind11 |
否则可以根据官方文档安装,但强烈不建议PyPI里的包(功能不完全)!
再退一步,不装也没关系,直接把它源码从Github仓库扒下来,后面会讲到要怎么用:
1 | $ git clone https://github.com/pybind/pybind11.git |
联合编译
方式一:setuptools [link]
这种方式相对传统(但常用),利用的是Python的打包工具setuptools(一般默认装了),可以利用pip进行管理。
示例目录如下:
1 | . |
main.cpp
是实现代码;1
int add(int i, int j) { return i + j; }
bind.cpp
是接口函数,记录需要编译哪些代码;1
2
3
4
5
6
7
8
9
10
11
12
13
namespace py = pybind11;
// example是项目名,即“import example“
PYBIND11_MODULE(example, m) {
// def是项目内的函数声明:
// 参数一是函数名,即“example.add(i, j)”
// 参数二是对应C++函数的指针
// 参数三是函数说明,即docstring
m.def("add", &add, "A function that adds two numbers");
}setup.py
和pyproject.toml
是setuptools的安装配置文件;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16from setuptools import setup
from pybind11.setup_helpers import Pybind11Extension
# module
ext_modules = [
Pybind11Extension(
"example", # 包名
["src/bind.cpp"] # 接口文件
),
]
setup(
name="example", # 包名(和上面一样)
ext_modules=ext_modules,
python_requires=">=3.6"
)1
2
3
4
5
6
7[build-system]
requires = [ # 依赖包
"setuptools>=42",
"wheel",
"pybind11~=2.6.1"
]
build-backend = "setuptools.build_meta"
准备完成后,可以在项目目录里面进行本地装包:
1 | $ pip install . --user |
显示安装成功即可在Python里面使用:
1 | import example |
方式二:cmake [link]
第二种方式是利用cmake编译出一个单独的项目.so
,不用装包,比较轻便化。
如果没装cmake的话需要先装好。
示例目录如下:
1 | . |
假如前面并没有安装pybind11,而是使用Github源码,则同样要放进目录里:
1 | . |
src
文件夹里的是C++实现代码,和上面说的一样;CMakeLists.txt
(名称不可变)是cmake的配置文件。1
2
3
4
5
6
7
8
9
10
11
12# cmake最低版本限制,实际上不写也行
cmake_minimum_required(VERSION 3.15)
# 项目名
project(example)
# 导入pybind
# add_subdirectory(pybind11) # 假如使用pybind11本地源码,则写这行,否则写下面那行
find_package(pybind11)
# 导入接口文件
pybind11_add_module(example src/bind.cpp)
准备好后,创建一个新文件夹来存放编译文件(为了不混乱):
1 | $ mkdir build |
假如出现这个错误:
1
2
3 By not providing "Findpybind11.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "pybind11",
but CMake did not find one.那就是因为pybind安装不完全(可能是使用了PyPI包),需要用别的方法装完整版或者扒Github源码。
一切顺利的话应该会达到进度100%:
1 | [ 50%] Building CXX object CMakeFiles/example.dir/bind.cpp.o |
然后它在build
文件夹里面创建的那个example.*.so
就是转码后文件,可以把他复制到你想要用的任何地方,在Python里面导入就行了:
1 | import example |
注意这种方法并没有安装包,所以没有了那个
example.*.so
文件就会失败。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 空空 如也 (´・ω・`)?!
评论