pybind11是一个轻量级的仅标头库,它在Python中公开C++类型,反之亦然,主要用于创建现有C++代码的Python绑定。它的目标和语法类似于David Abrahams的优秀Boost.Python库:通过使用编译时内省推断类型信息来最小化传统扩展模块中的样板代码。
Boost.Python的主要问题 - 以及创建这样一个类似项目的原因 - 是Boost。Boost是一套庞大而复杂的实用程序库,几乎可以与现有的所有C++编译器配合使用。这种兼容性有其成本:神秘的模板技巧和解决方法对于支持最古老和最错误的编译器样本是必要的。现在,C++11 兼容的编译器已广泛使用,这种繁重的机制已成为一种过大且不必要的依赖项。
将此库视为 Boost.Python 的一个小型自包含版本,其中剥离了与绑定生成无关的所有内容。如果没有注释,核心头文件只需要~4K行代码,并且依赖于Python(3.6 +或PyPy)和C++标准库。由于一些新的C++11语言功能(特别是:元组,lambda函数和可变参数模板),这种紧凑的实现成为可能。自创建以来,该库在许多方面已经超越了Boost.Python,导致在许多常见情况下绑定代码变得非常简单。
教程和参考文档在 pybind11.readthedocs.io 提供。手册的PDF版本可在此处获得。源代码始终在 github.com/pybind/pybind11 提供。
核心特性
pybind11 可以将以下核心C++特征映射到 Python:
接受并返回每个值、引用或指针的自定义数据结构的函数
实例方法和静态方法
重载函数
实例属性和静态属性
任意异常类型
枚举
回调
迭代器和范围
自定义运算符
单一和多重继承
数据结构
具有引用计数的智能指针,如
std::shared_ptr
具有正确参考计数的内部参考
C++具有虚拟(和纯虚拟)方法的类都可以在Python中扩展
糖果
除了核心功能之外,pybind11 还提供了一些额外的好处:
Python 3.6+和PyPy3 7.3支持与实现无关的接口(pybind11 2.9是最后一个支持Python 2和3.5的版本)。
可以将 C++11 lambda 函数与捕获的变量绑定。lambda 捕获数据存储在生成的 Python 函数对象中。
pybind11 尽可能使用 C++11 移动构造函数和移动赋值运算符来有效地传输自定义数据类型。
通过Pythons的缓冲协议很容易公开自定义数据类型的内部存储。这很方便,例如,用于在特征和NumPy等C++矩阵类之间进行快速转换,而无需昂贵的复制操作。
pybind11 可以自动对函数进行矢量化,以便将它们透明地应用于一个或多个 NumPy 数组参数的所有条目。
Python基于切片的访问和赋值操作只需几行代码即可支持。
所有内容都包含在几个头文件中;无需链接到任何其他库。
与 Boost.Python 生成的等效绑定相比,二进制文件通常至少小 2 倍。最近Pybind11的PyRosetta转换,一个巨大的Boost.Python绑定项目,报告二进制大小减少了5.4倍,编译时间减少了5.8倍。
函数签名在编译时预先计算(使用 ),从而导致较小的二进制文件。
constexpr
几乎不需要额外的努力,C++类型都可以像普通的Python对象一样被腌制和拔掉。
支持的编译器
叮当声/LLVM 3.3 或更高版本(对于苹果 Xcode 的叮当声,这是 5.0.0 或更高版本)
海湾合作委员会 4.8 或更高版本
微软视觉工作室 2017 或更高版本
英特尔经典C++编译器 18 或更高版本(在 CI 中测试 ICC 20.2)
赛格温/海湾合作委员会(之前在2.5.1上测试过)
NVCC(在 CI 中测试的 CUDA 11.0)
英伟达 PGI(在 CI 中测试 20.9)