pybind11快速实现c,c++ 与 python互通

简介

pybind11是一个轻量级的头文件库, 为Python和C、C++实现了类型互通,主要用于为现有C++代码创建Python绑定。它的目标和语法与Boost.Python库相似:通过使用编译时自省来推断类型信息,最大限度地减少传统扩展模块中的模板代码。

Boost是一个庞大而复杂的实用程序库套件,几乎可以与现存的所有C++编译器一起使用。这种兼容性是有代价的:为了支持最古老和最有问题的编译器,必须使用神秘的模板技巧和变通方法。现在与C++11兼容的编译器已经广泛使用,Boost已经包含过于庞大和不必要的依赖。

pybind11是Boost.Python的精简版本,剥离了所有与绑定生成无关的东西。在没有注释的情况下,核心头文件只需要大约4K行代码,并且依赖于Python(2.7或3.5+,或PyPy)和C++标准库。这种紧凑的实现是由于一些新的C++11语言特性(特别是:tuple、lambda函数和变量模板)而实现的。

教程和参考文档在https://pybind11.readthedocs.io/en/latest/提供。源代码可以在https://github.com/pybind/pybind11/获得。

核心功能

以下核心C ++功能可以映射到Python

  • 函数入参和返回值可以是自定义数据结构的值、引用或者指针
  • 实例方法和静态方法
  • 重载
  • 实例属性和静态属性
  • 任意异常类型
  • 枚举
  • 回调
  • 迭代器和range
  • 自定义操作符
  • 单继承和多继承
  • STL数据结构
  • 带有引用计数的智能指针,类似于std::shared_ptr
  • 正确的引用计数的内部引用
  • 带有虚函数和纯虚函数的C ++类可以在Python中扩展

其他有用功能

  • Python 2.7,3.5+和PyPy/PyPy3 7.3支持与实现无关接口。
  • 将C++11 lambda函数与捕获的变量绑定在一起。lambda捕获的数据存储在生成的Python函数对象中。
  • pybind11使用C++11 move constructors 和 move assignment operators从而有效地转换自定义数据类型。
  • 通过Python的buffer协议,可以很容易地公开内部存储的自定义数据类型,比如C++矩阵类型如Eigen和NumPy之间进行快速转换。
  • pybind11可以自动将函数矢量化,以便它们透明地应用于以NumPy数组为参数的所有条目。
  • 只需几行代码就可以支持Python的基于切片的访问和赋值操作。
  • 一切都只包含在几个头文件中,没有必要链接任何其他库。
  • 与Boost.Python比二级制文件更小,编译时间更短,5倍速以上。
  • 函数签名是在编译时预先计算的(使用constexpr),生成更小的二进制文件。
  • 只需很少的额外工作,C ++类型就可以像Python对象一样进行pickled和unpickled。

快速入门

  • 安装

调试环境:ubuntu 20.04.3 LTS

# pip install pybind11
# git clone https://github.com/pybind/pybind11
# cd pybind11/include

创建文件example.cpp

#include <pybind11/pybind11.h>

int add(int i, int j) {
    return i + j;
}

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example plugin"; // optional module docstring

    m.def("add", &add, "A function that adds two numbers");
}

编译执行

#  c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
# ls
example.cpp  example.cpython-38-x86_64-linux-gnu.so  pybind11
# python
Python 3.8.8 (default, Apr 13 2021, 19:58:26) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> example.add(1, 2)
3

在c++中调用python

demo.cpp

#include <iostream>
#include <pybind11/embed.h>

namespace py = pybind11;
using namespace std;

int main()
{
    cout << "Hello PyBind World" << endl;

    // start the interpreter and keep it alive
    py::scoped_interpreter guard{}; 
    py::module math = py::module::import("math");
    py::object result = math.attr("sqrt")(25);
    std::cout << "Sqrt of 25 is: " << result.cast<float>() << std::endl;
}

新建CMakeLists.txt

project(pybind_demo)
cmake_minimum_required(VERSION 3.13)
set(CMAKE_CXX_STANDARD 14)  

include(FetchContent)
FetchContent_Declare(
    pybind11
    GIT_REPOSITORY https://github.com/pybind/pybind11.git
    GIT_TAG        v2.6.2
    GIT_SHALLOW    TRUE
)

FetchContent_MakeAvailable(pybind11)

add_executable(demo demo.cpp)
target_link_libraries(demo PRIVATE pybind11::embed)

编译执行:

$ cmake .
CMake Warning (dev) at CMakeLists.txt:1 (project):
  Policy CMP0048 is not set: project() command manages VERSION variables.
  Run "cmake --help-policy CMP0048" for policy details.  Use the cmake_policy
  command to set the policy and suppress this warning.

  The following variable(s) would be set to empty:

    CMAKE_PROJECT_VERSION
    CMAKE_PROJECT_VERSION_MAJOR
    CMAKE_PROJECT_VERSION_MINOR
    CMAKE_PROJECT_VERSION_PATCH
This warning is for project developers.  Use -Wno-dev to suppress it.

-- pybind11 v2.6.2 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/andrew/code/pybind11/include
$ make
Scanning dependencies of target demo
[ 50%] Building CXX object CMakeFiles/demo.dir/demo.cpp.o
[100%] Linking CXX executable demo
[100%] Built target demo
$ ./demo 
Hello PyBind World
Sqrt of 25 is: 5

以上步骤需要保证对github的访问。参考资料:https://blog.devgenius.io/calling-python-and-c-code-using-pybind-99ab7fefa685

在python中调用c++

example.cpp

#include <pybind11/embed.h>

int multiply(int i, int j) {
    return i * j;
}

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example plugin"; // optional module docstring
    m.def("multiply", &multiply, "A function which multiplies two numbers");
}

新建CMakeLists.txt

cmake_minimum_required(VERSION 3.13)
project(pybind_demo)
set(CMAKE_CXX_STANDARD 14)  

include(FetchContent)
FetchContent_Declare(
    pybind11
    GIT_REPOSITORY https://github.com/pybind/pybind11.git
    GIT_TAG        v2.6.2
    GIT_SHALLOW    TRUE
)

FetchContent_MakeAvailable(pybind11)

pybind11_add_module(example example.cpp)
target_compile_features(example PUBLIC cxx_std_14)
set_target_properties(example PROPERTIES SUFFIX ".so")

编译执行:

$ cmake .
-- pybind11 v2.6.2 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/andrew/code/pybind11/include/exmaple
$ make
Scanning dependencies of target example
[ 50%] Building CXX object CMakeFiles/example.dir/example.cpp.o
[100%] Linking CXX shared module example.so
[100%] Built target example
$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  CMakeLists.txt  _deps  example.cpp  example.so  Makefile
$ python
Python 3.8.8 (default, Apr 13 2021, 19:58:26) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> example.multiply(3, 2)
6
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容