定义扩展模块
************

针对 CPython 的 C 扩展就是一个共享库（例如，Linux 上的 ".so" 文件，
Windows 上的 ".pyd" DLL），它可被加载到 Python 进程中（例如，它可以用
兼容的编译器设置进行编译），而这会导出一个 *导出钩子* 函数 (或旧式的
初始化函数)。

要在默认情况下可被导入 (也就是说，通过
"importlib.machinery.ExtensionFileLoader")，共享库必须在 "sys.path" 中
可用，并且必须命名为模块名之后加一个在
"importlib.machinery.EXTENSION_SUFFIXES" 中列出的扩展名。

备注:

  构建、打包和分发扩展模块最好使用第三方工具完成，并且超出了本文的范围
  。一个合适的工具是 Setuptools，其文档可以在
  https://setuptools.pypa.io/en/latest/setuptools.html 上找到。


扩展导出钩子
============

Added in version 3.15: 对 "PyModExport_*<name>*" 导出钩子的支持是在
Python 3.15 中增加的。 定义模块的旧方式仍然可用：如果你计划支持更早的
Python 版本可以查阅 PyInit 函数 一节或本文档的较早版本。

导出钩子必须是具有以下签名的导出函数：

PySlot *PyModExport_modulename(void)

对于具有仅限 ASCII 名称的模块，导出钩子 必须被命名为
"PyModExport_*<name>*"，其中 "<name>" 以模块名称替换。

对于非 ASCII 模块名称，则导出钩子必须被命名为 "PyModExportU_*<name>*"
(注意增加了 "U")，其中 "<name>" 使用 Python 的 *punycode* 编码格式进行
编码并将连字符替换为下划线。 在 Python 中：

   def hook_name(name):
       try:
           suffix = b'_' + name.encode('ascii')
       except UnicodeEncodeError:
           suffix = b'U_' + name.encode('punycode').replace(b'-', b'_')
       return b'PyModExport' + suffix

导出钩子将返回由 "PySlot" 条目组成的数组，以一个槽位 ID 为 "0" 的条目
作为终结。 这些槽位描述了模块应当如何被创建和初始化。

这个数组必须保持可用与恒定直到解释器关闭。 通常，它应当使用 "static"
存储。 建议针对任何动态行为使用 "Py_mod_create" 和 "Py_mod_exec" 槽位
。

导出钩子可以返回 "NULL" 并设置一个异常来发出失败信号。

It is recommended to define the export hook function using a helper
macro:

PyMODEXPORT_FUNC
    * 属于 稳定 ABI 自 3.15 版起.*

   Declare an extension module export hook. This macro:

   * specifies the PySlot* return type,

   * 添加平台所需的任何特殊链接声明，以及

   * 对于 C++，将函数声明为 "extern "C""。

例如，一个名为 "spam" 的模块可以这样定义:

   PyABIInfo_VAR(abi_info);

   static PySlot spam_slots[] = {
       PySlot_STATIC_DATA(Py_mod_abi, &abi_info),
       PySlot_STATIC_DATA(Py_mod_name, "spam"),
       PySlot_FUNC(Py_mod_init, spam_init_function),
       ...
       PySlot_END
   };

   PyMODEXPORT_FUNC
   PyModExport_spam(void)
   {
       return spam_slots;
   }

The export hook is typically the only non-"static" item defined in the
module's C source.

The hook should be kept short. If it does more than "return" a static
array, several caveats apply:

* If you need to use any Python C API, it is recommended to call
  "PyABIInfo_Check()" first to raise an exception, rather than crash,
  in common cases of ABI mismatch.

* Code in the export hook must never rely on the *GIL*: *free-threaded
  builds* of Python can only check the "Py_mod_gil" slot (or the lack
  of it) after the hook returns,

* Similarly, the hook may be called in any subinterpreter, since the
  "Py_mod_multiple_interpreters" slot (or lack of it) is only checked
  after the hook returns.

例如:

   PyMODEXPORT_FUNC
   PyModExport_modulename(void)
   {
      if (PyABIInfo_Check(&abi_info, "modulename") < 0) {
         /* ABI mismatch. It's not safe to examine the raised exception. */
         return NULL;
      }

      /* use Python API (as little as possible); don't rely on GIL */

      return modulename_slots;
   }

备注:

  It is possible to export multiple modules from a single shared
  library by defining multiple export hooks. However, importing  them
  requires a custom importer or suitably named copies/links of the
  extension file, because Python's import machinery only finds the
  function corresponding to the filename. See the Multiple modules in
  one library section in **PEP 489** for details.


多阶段初始化
============

The process of creating an extension module follows several phases:

* Python finds and calls the export hook to get information on how to
  create the module.

* Before any substantial code is executed, Python can determine which
  capabilities the module supports, and it can adjust the environment
  or refuse loading an incompatible extension. Slots like
  "Py_mod_abi", "Py_mod_gil" and "Py_mod_multiple_interpreters"
  influence this step.

* By default, Python itself then creates the module object -- that is,
  it does the equivalent of calling "__new__()" when creating an
  object. This step can be overridden using the "Py_mod_create" slot.

* Python sets initial module attributes like "__package__" and
  "__loader__", and inserts the module object into "sys.modules".

* Afterwards, the module object is initialized in an extension-
  specific way -- the equivalent of "__init__()" when creating an
  object, or of executing top-level code in a Python-language module.
  The behavior is specified using the "Py_mod_exec" slot.

This is called *multi-phase initialization* to distinguish it from the
legacy (but still supported) single-phase initialization, where an
initialization function returns a fully constructed module.

在 3.5 版本发生变更: 增加了对多阶段初始化的支持 (**PEP 489**)。


多个模块实例
============

By default, extension modules are not singletons. For example, if the
"sys.modules" entry is removed and the module is re-imported, a new
module object is created and, typically, populated with fresh method
and type objects. The old module is subject to normal garbage
collection. This mirrors the behavior of pure-Python modules.

额外的模块实例可能会在 子解释器 中或者 Python 运行时重新初始化之后
("Py_Finalize()" 和 "Py_Initialize()") 被创建。在这些情况下，模块实例
间共享 Python  对象可能导致程序崩溃或未定义的行为。

为避免这种问题，每个扩展模块的实例都应当是 *隔离的*: 对一个实例的修改
不应隐式地影响其他的实例，以及模块所拥有的全部状态，包括对 Python 对象
的引用，都应当是特定模块实例专属的。请参阅 隔离扩展模块 了解更多的细节
和实用的指南。

一个避免这些问题的简单方式是 针对重复的初始化引发一个错误。

所有模块都应当支持 子解释器，否则就要显式地发出缺乏支持的信号。 这往往
是通过隔离或阻止重复的初始化，如上文所述。一个模块也可以使用
"Py_mod_multiple_interpreters" 槽位将其限制于主解释器中。


"PyInit" 函数
=============

自 3.15 版起已处于 Soft deprecated 状态: This functionality will not
get new features, but there are no plans to remove it.

Instead of "PyModExport_modulename()", an extension module can define
an older-style *initialization function* with the signature:

PyObject *PyInit_modulename(void)

Its name should be "PyInit_*<name>*", with "<name>" replaced by the
name of the module. For non-ASCII module names, use "PyInitU_*<name>*"
instead, with "<name>" encoded in the same way as for the export hook
(that is, using Punycode with underscores).

If a module exports both "PyInit_*<name>*" and "PyModExport_*<name>*",
the "PyInit_*<name>*" function is ignored.

Like with "PyMODEXPORT_FUNC", it is recommended to define the
initialization function using a helper macro:

PyMODINIT_FUNC

   声明一个扩展模块初始化函数。这个宏：

   * 指定了 PyObject* 返回类型，

   * 添加平台所需的任何特殊链接声明，以及

   * 对于 C++，将函数声明为 "extern "C""。

Normally, the initialization function ("PyInit_modulename") returns a
"PyModuleDef" instance with non-"NULL" "m_slots". This allows Python
to use multi-phase initialization.

Before it is returned, the "PyModuleDef" instance must be initialized
using the following function:

PyObject *PyModuleDef_Init(PyModuleDef *def)
    * 属于 稳定 ABI 自 3.5 版起.*

   确保模块定义是一个正确初始化的 Python 对象，并正确报告其类型以及引
   用计数。

   返回强制转换为 "PyObject*" 的 *def*，或者如果出现错误则返回 "NULL"
   。

   Calling this function is required before returning a "PyModuleDef"
   from a module initialization function. It should not be used in
   other contexts.

   请注意 Python 会假定 "PyModuleDef" 结构体是静态分配的。此函数可以返
   回一个新引用或借用引用；这个引用不可被释放。

   Added in version 3.5.

例如，一个名为 "spam" 的模块可以这样定义:

   static struct PyModuleDef spam_module = {
       .m_base = PyModuleDef_HEAD_INIT,
       .m_name = "spam",
       ...
   };

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       return PyModuleDef_Init(&spam_module);
   }


旧式的单阶段初始化
------------------

自 3.15 版起已处于 Soft deprecated 状态: 单阶段初始化是一种用于初始化
扩展模块的旧机制，它具有已知的缺点和设计瑕疵。建议扩展模块作者改用多阶
段初始化。However, there are no plans to remove support for it.

In single-phase initialization, the old-style initialization function
("PyInit_modulename") should create, populate and return a module
object. This is typically done using "PyModule_Create()" and functions
like "PyModule_AddObjectRef()".

单阶段初始化与 默认方式 的主要区别如下：

* 单阶段模块本质上是（更准确地说，*包含*）"单例对象"。

  当模块首次初始化时，Python 会保存该模块 "__dict__" 中的内容（通常包
  括模块的函数和类型等）。

  对于后续导入操作，Python 不会再次调用初始化函数，而是创建一个带有新
  "__dict__" 的模块对象，并将已保存的内容复制到其中。例如，假设有一个
  单阶段模块 "_testsinglephase" [1] 定义了函数 "sum" 和异常类 "error":

     >>> import sys
     >>> import _testsinglephase as one
     >>> del sys.modules['_testsinglephase']
     >>> import _testsinglephase as two
     >>> one is two
     False
     >>> one.__dict__ is two.__dict__
     False
     >>> one.sum is two.sum
     True
     >>> one.error is two.error
     True

  该具体行为应被视为 CPython 的实现细节。

* 为解决 "PyInit_modulename" 函数不接受 *spec* 参数的限制，导入机制会
  保存部分状态，并在 "PyInit_modulename" 调用期间将其应用于首个匹配的
  模块对象。具体表现为：当导入子模块时，该机制会将父包名称自动前置到模
  块名前。

  单阶段 "PyInit_modulename" 函数应当尽早创建"其所属"模块对象，该操作
  需在任何其他模块对象创建之前完成。

* 不支持非 ASCII 模块名 ("PyInitU_modulename")。

* 单阶段模块支持模块查找函数如 "PyState_FindModule()"。

* The module's "PyModuleDef.m_slots" must be NULL.

[1] "_testsinglephase" 是一个在 CPython 的自我测试套件中使用的内部模块
    ；你的安装版可能包括它也可能不包括它。
