4. 构建 C 和 C++ 扩展¶
CPython 的 C 扩展是一个共享库(例如,Linux 上的 .so
文件,Windows 上的 .pyd
文件),它导出一个初始化函数。
为了可以导入,该共享库必须在 PYTHONPATH
上可用,并且必须以模块名命名,并带有适当的扩展名。 当使用 setuptools 时,会自动生成正确的文件名。
初始化函数的签名如下
它返回一个完全初始化的模块,或者一个 PyModuleDef
实例。有关详细信息,请参阅初始化 C 模块。
对于仅包含 ASCII 字符的模块名称,该函数必须命名为 PyInit_<modulename>
,其中 <modulename>
替换为模块的名称。 当使用多阶段初始化时,允许使用非 ASCII 模块名称。 在这种情况下,初始化函数名称为 PyInitU_<modulename>
,其中 <modulename>
使用 Python 的 *punycode* 编码进行编码,并将连字符替换为下划线。 在 Python 中
def initfunc_name(name):
try:
suffix = b'_' + name.encode('ascii')
except UnicodeEncodeError:
suffix = b'U_' + name.encode('punycode').replace(b'-', b'_')
return b'PyInit' + suffix
通过定义多个初始化函数,可以从单个共享库导出多个模块。 但是,导入它们需要使用符号链接或自定义导入器,因为默认情况下只会找到与文件名对应的函数。 有关详细信息,请参阅 PEP 489 中的 “一个库中的多个模块” 部分。
4.1. 使用 setuptools 构建 C 和 C++ 扩展¶
Python 3.12 及更高版本不再附带 distutils。请参考 setuptools
的文档 https://setuptools.readthedocs.io/en/latest/setuptools.html,以了解更多关于如何使用 setuptools 构建和分发 C/C++ 扩展的信息。