

Pybind11 理解
source link: http://satanwoo.github.io/2020/08/29/Pybind11/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Pybind11 源码分析
MNN 社区上提供了通过 Python 使用 MNN 的方式,具体可以见:
https://github.com/alibaba/MNN/tree/master/pymnn/src
我们通过 Pybind11 来提供比较优雅的桥接方式。由于 Pybind 11 是一层抽象 C++ 到 Python 桥接的库,上层封装了很多难以理解的细节和流程,本文就带大家抽丝剥茧一下。
关于 Python 桥接,如果你不是很了解,那么在阅读本文之前,请记住如下两句话:
代码必须要以传统的 module 添加类的方式来进行,相关代码是:
- PyInitModule
- PyModule_AddObject(xxx)
Python 没办法直接编写 C++ Extension,都是通过再包一层 C 方法 (Python 自身的 C 接口)的方式来进行。
换句话说,不管什么,都需要以一个 module 为载体,且需要name
创建模块方法
因此我们的入口就在 PYBIND11_MODULE(name, variable)
全部的宏就是:
#define PYBIND11_MODULE(name, variable) \
【1】static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \
【2】PYBIND11_PLUGIN_IMPL(name) { \
【3】PYBIND11_CHECK_PYTHON_VERSION \
auto m = pybind11::module(PYBIND11_TOSTRING(name)); \
try { \
PYBIND11_CONCAT(pybind11_init_, name)(m); \
return m.ptr(); \
} PYBIND11_CATCH_INIT_EXCEPTIONS \
} \
void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable)
比较晦涩,我们以 mnn
来举例,帮宏全部展开来探索下。
首先声明一个函数
static void pybind11_init_mnn(pybind11::module &);
,在宏的最后会有实现。PYBIND11_PLUGIN_IMPL(mnn)
这一步是必要的一步,所有 Python 的扩展模块都需要声明对应的初始化方法,用于注册被调用。import mnn
就会调用init_mnn
这样的方法。initmnn
里面定义了pybind11_init_wrapper
这是真正的初始化实现。(注意 static 声明)pybind11_init_wrapper
里面真正的实现分为几步:构造一个
module
对象(class module),auto m = pybind11::module(PYBIND11_TOSTRING(name));
调用之前声明的
pybind11_init_mnn
函数,传入module对象,仿造 Python C Extension 的方式来添加方法、定义、变量等。pybind11_init_mnn(m)
实现
pybind11_init_mnn {xxx}
所以一切核心的关键就是在
class module
,抛开繁杂的东西:第一步,创建一个 CPython 中的 module object,见:
所以,本质上无论 Pybind11 在干什么,都是利用 CPython 底层的技术在那里操作。
把对应的方法加入到这个 CPython Module 中,如下:
创建类的方法相对难一点,但是也不难理解,我们还是找到根源 class class_
(其实一切只要理解 Pybind11 是用 C++ 去模拟 CPython 的流程就行了)
找到对应的构造函数,首先从函数签名上我们就能窥探一些东西:

scope
对应类所属的模块。name
就是类名。Extra
就是 C++ 模版机制对应的真正类。
看起来上面和对应的 Python 类型初始化没关系,来看看是不是 generic_type::initialize
造成的。

make_new_python_type
这名字一看就很符合,哈哈,点进去一看,果然是类型初始化流程。

简要概括下添加方法的实现。
生成模版化的初始化模块方法,即 Wrapper 方法。
提供一个仿造
Python Module
对象(便于C++
编写 / 使用智能指针管理引用计数),在对应的自定义函数里面添加对应Module
的实现。
Recommend
-
186
之前知识星球有同学问道了这样一个问题:Node 环境和浏览器环境有什么区别?这样的思考很值得鼓励,在对比中学习,很容易将一个抽象的知识具象化。当时的回答只是简单的画了个图,感觉有必要用此文来深入挖掘一下 二、什么是前端,什么是后端? 想必没有哪个同学不...
-
171
《深入理解ES6》阅读笔记 --- 用模块封装代码icepy隐居山野的农夫
-
133
website upgrading… 京ICP...
-
40
README.md
-
13
Speeding up Python with C++ and pybind11 In two previous posts, I described using cython and
-
13
Python, C++, Pybind11, and string_view The other day I was using the excellent pybind11 to bridge some Python code and C++ code. The C++ code was performance critical,...
-
11
给 Python 算法插上性能的翅膀——pybind11 落地实践作者:jesonxiang(向乾彪),腾讯 TEG 后台开发工程师1. 背景目前 AI 算法开发特别是训练基本都以 Python 为主,主流的 AI 计算框架如 TensorFlow、PyTorch 等都提供了丰富的...
-
10
Using STL Containers with pybind112021-12-23Python387 words 2 mins read 26 times readIn my
-
5
为Cpp实现的功能提供Python API接口-Pybind11 兴趣与业余时间开发的CVTK项目,除了继续完善和添加算法到
-
7
jvm jni 及 pvm pybind11 大批量数据传输及优化 PS:要转载请注明出处,本人版权所有。PS: 这个只是基于《...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK