文章插图
导读:使用 C 扩展为 Python/ target=_blank class=infotextkey>Python 提供特定功能 。
本文字数:7993,阅读时长大约: 9分钟
使用 C 扩展为 Python 提供特定功能 。
在前一篇文章中,我介绍了 opensource.com 。在大多数系统上,CPython 是默认的解释器,而且根据民意调查显示,它还是最流行的解释器 。Cpython 的独有功能是使用扩展 API 用 C 语言编写 Python 模块 。用 C 语言编写 Python 模块允许你将计算密集型代码转移到 C,同时保留 Python 的易用性 。
在本文中,我将向你展示如何编写一个 C++ 扩展模块 。使用 C++ 而不是 C,因为大多数编译器通常都能理解这两种语言 。我必须提前说明缺点:以这种方式构建的 Python 模块不能移植到其他解释器中 。它们只与 CPython 解释器配合工作 。因此,如果你正在寻找一种可移植性更好的与 C 语言模块交互的方式,考虑下使用 docs.python.org 模块 。
源代码
和往常一样,你可以在 github.com 上找到相关的源代码 。仓库中的 C++ 文件有以下用途:
?
my_py_module.cpp
: Python 模块MyModule
的定义?
my_cpp_class.h
: 一个头文件 - 只有一个暴露给 Python 的 C++ 类?
my_class_py_type.h/cpp
: Python 形式的 C++ 类?
pydbg.cpp
: 用于调试的单独应用程序本文构建的 Python 模块不会有任何实际用途,但它是一个很好的示例 。
构建模块
在查看源代码之前,你可以检查它是否能在你的系统上编译 。opensource.com 来创建构建的配置信息,因此你的系统上必须安装 CMake 。为了配置和构建这个模块,可以让 Python 去执行这个过程:
-
$ python3 setup.py build
或者手动执行:
-
$ cmake -B build
-
$ cmake --build build
之后,在
/build
子目录下你会有一个名为MyModule. so
的文件 。定义扩展模块
首先,看一下
my_py_module.cpp
文件,尤其是PyInit_MyModule
函数:-
PyMODINIT_FUNC
-
PyInit_MyModule(void) {
-
PyObject* module = PyModule_Create(&my_module);
-
-
PyObject *myclass = PyType_FromSpec(&spec_myclass);
-
if (myclass == NULL){
-
return NULL;
-
}
-
Py_INCREF(myclass);
-
-
if(PyModule_AddObject(module, "MyClass", myclass) < 0){
-
Py_DECREF(myclass);
-
Py_DECREF(module);
-
return NULL;
-
}
-
return module;
-
}
这是本例中最重要的代码,因为它是 CPython 的入口点 。一般来说,当一个 Python C 扩展被编译并作为共享对象二进制文件提供时,CPython 会在同名二进制文件中(
.so
)搜索PyInit_
函数,并在试图导入时执行它 。无论是声明还是实例,所有 Python 类型都是 docs.python.org 的一个指针 。在此函数的第一部分中,
module
通过PyModule_Create(...)
创建的 。正如你在module
详述(my_py_module
,同名文件)中看到的,它没有任何特殊的功能 。之后,调用 docs.python.org 为自定义类型
推荐阅读
- Python 教你快速批量下载抖音去水印短视频
- 为什么我抓不到baidu的数据包?
- Python破解24点游戏
- 为什么Java线程没有Running状态?
- 一次服务器沦陷为肉鸡后的排查过程
- 国外大学生用AI写论文,还次次拿到A
- 为什么短短两周之后就鲜有人继续讨论ChatGPT了?
- 开发一个简单的热搜微信小程序
- 戚薇|戚薇二胎产后首露面,发长文卖惨为月子中心打广告,网友:快封杀
- 为什么有些腕表被称为医生表?