Pybind11 简介

Pybind11 简介

本文使用 Zhihu On VSCode 创作并发布


本篇内容主要来自于官方文档

Pybind11 是一个轻量级的 C++ 库,用于将你的 C++ 代码暴露给 Python 调用(反之也可,但主要还是前者)。Pybind11 借鉴了 Boost::Python 库的设计,但使用了更为简洁的实现方式,使用了大量 C++11 的新特性,更易于使用。

特点

Pybind11 允许你在 C++ 代码中使用如下特性,并在 Python 中方便地调用。

  • 允许函数参数使用自定义类型(包括值、指针和引用);
  • 类成员函数与静态函数;
  • 函数重载;
  • 类成员与静态成员;
  • 异常;
  • 枚举;
  • 回调函数;
  • 迭代器和范围(range);
  • 自定义 operator
  • 继承(包括多重继承);
  • STL 中的数据结构;
  • 智能指针;
  • 带有引用计数的内部引用;
  • 在 C++ 中定义虚方法,并在 Python 中进行扩展;

Pybind11 的优点有:

  • 兼容性强,支持 Python2.7、Python3.x、PyPy (PyPy2.7 >= 5.7);
  • 可以在 C++ 中使用 lambda 表达式,并在 Python 中使用捕获的变量;
  • 大量使用移动特性,保证数据转移时的性能;
  • 可以很方便地通过 Python buffer protocol 进行数据类型的转移;
  • 可以很方便地对函数进行向量化加速;
  • 支持使用 Python 的切片语法;
  • Pybind11 是 header-only 的,只需要包含头文件即可;
  • 相比于 Boost::Python,生成的二进制文件体积更小;
  • 函数签名通过 constexper 提前计算,进一步减小二进制文件体积;
  • C++ 中的类型可以很容易地进行序列化/反序列化;

以下是作者写的内容,非文档内容

Python 以其灵活和易于上手的特点,成为了当下炙手可热的编程语言。然而,动态解释型语言的特点限制了其性能。因此在需要性能的地方,往往使用 C、C++ 等传统高性能语言实现(如 numpy 这种科学计算库),并在 Python 中调用。这就是所谓的混合编程,发挥各自的优势,取长补短。

Pybind11 出来以前,Python 和 C/C++ 混合编程的手段包括:

  • Python 的 C-API (Python.h)
  • SWIG
  • Python 的 ctypes 模块
  • Cython
  • Boost::Python

第一个,在 C++ 代码中包含 Python.h,并使用 Python 的 C-API 对 Python 语言进行操作。需要对 Python 底层实现有一定了解,比如自己管理引用计数等,比较繁琐;

第二个 SWIG,用于将 C/C++ 代码暴露给其它语言的工具;使用时,需要编写一个复杂的 SWIG 接口声明文件,并使用 SWIG 自动生成使用 Python-C-API 的 C 代码(可读性很差);

第三个,使用 Python 内置的 ctypes 模块,提供了 C 语言中的类型,以及直接调用动态链接库(.dll、.so)的能力;缺点是依赖于 C 的原生类型,对自定义类型支持不好;

第四个,Cython,是 Python 语言的扩展,支持原生 Python,但引入了自己额外的语法;使用 Cython 编译器可以将 Cython 代码自动转化为 C 代码,并编译成动态链接库供 Python 调用;相比于 SWIG 来说更加方便,生成的代码更加易读;

第五个,使用 Boost::Python 库操纵 Python 对象,和使用 Python-C-API 原理是一样的,只不过提供了更易于使用的库。缺点是引入 Boost 依赖较重,而 Pybind11 正是为了提供一个轻量级的解决方案而出现的;

作者自己只使用过 Cython,使用的体验还是不错的,Cython 的语法和 Python 很像,转化后的 C 代码运行效率也很高。但 Pybind11 出来后,越来越多人选择 Pybind11 作为混合编程的解决方案。因此,作者建议,如果遇到需要 Python C/C++ 混合编程的需求,尽量使用 Pybind11 或 Cython,ctypes 和 Python-C-API 方案尽量不考虑。

关于 Python 与 C/C++ 混合编程,知乎上有一些不错的资料:

编辑于 2020-06-13 00:40