@@ -2,14 +2,16 @@ PEP: 793
22Title: PyModExport: A new entry point for C extension modules
33Author: Petr Viktorin <encukou@gmail.com>
44Discussions-To: https://discuss.python.org/t/93444
5- Status: Accepted
5+ Status: Final
66Type: Standards Track
77Created: 23-May-2025
88Python-Version: 3.15
99Post-History: `14-Mar-2025 <https://discuss.python.org/t/84498/ >`__,
1010 `27-May-2025 <https://discuss.python.org/t/93444/ >`__,
1111Resolution: `23-Oct-2025 <https://discuss.python.org/t/93444/46 >`__
1212
13+ .. canonical-doc :: :ref:`py3.15:extension-modules`
14+
1315
1416Abstract
1517========
@@ -21,7 +23,7 @@ This allows extension authors to avoid using a statically allocated
2123``PyObject ``, lifting the most common obstacle to making one compiled library
2224file usable with both regular and free-threaded builds of CPython.
2325
24- To make this viable, we also specify new module slot types to replace
26+ To make this viable, we also specify new module slot IDs to replace
2527``PyModuleDef ``'s fields, and to allow adding a *token * similar to the
2628``Py_tp_token `` used for type objects.
2729
@@ -131,8 +133,8 @@ This proposal does away with fixed fields and proposes using a slots array
131133directly, without a wrapper struct.
132134
133135The ``PyModuleDef_Slot `` struct does have some downsides compared to fixed fields.
134- We believe these are fixable, but leave that out of scope of this PEP
135- (see “Improving slots in general” in the Possible Future Directions section).
136+ We believe these are fixable, but leave that out of scope of this PEP.
137+ (Note: this was done in :pep: ` 820 `, still in Python 3.15.)
136138
137139
138140Tokens
@@ -187,6 +189,8 @@ like this:
187189
188190 PyModuleDef_Slot *PyModExport_<NAME>(void);
189191
192+ .. note :: :pep:`820` changed the return type to ``PySlot *``.
193+
190194where ``<NAME> `` is the name of the module.
191195For non-ASCII names, it will instead look for ``PyModExportU_<NAME> ``,
192196with ``<NAME> `` encoded as for existing ``PyInitU_* `` hooks
@@ -223,14 +227,13 @@ A new function will be added to create a module from an array of slots:
223227
224228 PyObject *PyModule_FromSlotsAndSpec(const PyModuleDef_Slot *slots, PyObject *spec)
225229
230+ .. note :: :pep:`820` changed the first argument type to ``PySlot *``.
231+
226232The *slots * argument must point to an array of ``PyModuleDef_Slot `` structures,
227233terminated by a slot with ``slot=0 `` (typically written as ``{0} `` in C).
228- There are no required slots, though *slots * must not be ``NULL ``.
229- It follows that minimal input contains only the terminator slot.
230-
231- .. note ::
232-
233- If :pep: `803 ` is accepted, the ``Py_mod_abi `` slot will be mandatory.
234+ The ``Py_mod_abi `` slot is required (see :pep: `803 `); all other slots
235+ are optional.
236+ It follows that *slots * must not be ``NULL ``.
234237
235238The *spec * argument is a duck-typed ModuleSpec-like object, meaning that any
236239attributes defined for ``importlib.machinery.ModuleSpec `` have matching
@@ -373,7 +376,7 @@ Bits & Pieces
373376-------------
374377
375378A ``PyMODEXPORT_FUNC `` macro will be added, similar to the ``PyMODINIT_FUNC ``
376- macro but with ``PyModuleDef_Slot * `` as the return type.
379+ macro but with ``PySlot * `` as the return type.
377380
378381A ``PyModule_GetStateSize `` function will be added to retrieve the size set
379382by ``Py_mod_state_size `` or ``PyModuleDef.m_size ``.
@@ -397,6 +400,9 @@ The ``PyInit_*`` export hook will be
397400
398401New API summary
399402---------------
403+
404+ .. note :: This summary was updated with a change from :pep:`820`.
405+
400406Python will load a new module export hook, with two variants:
401407
402408.. code-block :: c
@@ -408,7 +414,7 @@ The following functions will be added:
408414
409415.. code-block :: c
410416
411- PyObject *PyModule_FromSlotsAndSpec(const PyModuleDef_Slot *, PyObject *spec)
417+ PyObject *PyModule_FromSlotsAndSpec(const PySlot *, PyObject *spec)
412418 int PyModule_Exec(PyObject *)
413419 int PyModule_GetToken(PyObject *, void**)
414420 PyObject *PyType_GetModuleByToken(PyTypeObject *type, const void *token)
@@ -477,6 +483,15 @@ Here is a guide to convert an existing module to the new API, including
477483some tricky edge cases.
478484It should be moved to a HOWTO in the documentation.
479485
486+ .. note ::
487+
488+ The guide is available at :ref: `py3.15:abi3t-howto-modexport `.
489+ (It is part of the ``abi3t `` migration HOWTO since switching to
490+ ``PyModExport `` doesn't bring benefits in 3.15 if you don't also
491+ adopt ``abi3t ``.)
492+
493+ This section contains the original, outdated guide.
494+
480495This guide is meant for hand-written modules. For code generators and language
481496wrappers, the :ref: `pep793-shim ` below may be more useful.
482497
@@ -585,24 +600,29 @@ The following implementation can be copied and pasted to a project; only the
585600names ``PyInit_examplemodule `` (twice) and ``PyModExport_examplemodule `` should
586601need adjusting.
587602
588- When added to the :ref: `pep793-example ` below and compiled with a
589- non-free-threaded build of this PEP's reference implementation, the resulting
590- extension is compatible with non-free-threading 3.9+ builds, in addition to a
603+ .. note ::
604+
605+ This section was updated for :pep: `820 `.
606+
607+ When compiled together with the :ref: `pep793-example ` below on a
608+ non-free-threaded build of Python 3.15, the resulting
609+ extension is compatible with non-free-threading 3.11+ builds, in addition to a
591610free-threading build of the reference implementation.
592611(The module must be named without a version tag, e.g. ``examplemodule.so ``,
593612and be placed on ``sys.path ``.)
594613
595614Full support for creating such modules will require backports of some new
596615API, and support in build/install tools. This is out of scope of this PEP.
597616(In particular, the demo “cheats” by using a subset of Limited API 3.15 that
598- *happens to work * on 3.9; a proper implementation would use Limited API 3.9
599- with backport shims for new API like ``Py_mod_name ``.)
617+ *happens to work * on 3.11, and includes a few hacks.
618+ A proper implementation would use Limited API 3.11 with cleaner backport shims
619+ for new API like ``Py_mod_name ``.)
600620
601621This implementation places a few additional requirements on the slots array:
602622
603- - Slots that correspond to `` PyModuleDef `` members must come first .
623+ - `` Py_mod_slots `` and `` Py_slot_subslots `` are not supported .
604624- A ``Py_mod_name `` slot is required.
605- - Any ``Py_mod_token `` must be set to `` &module_def_and_token ``, defined here.
625+ - Any ``Py_mod_token `` must be set to the `` MOD_TOKEN `` defined here.
606626
607627.. literalinclude :: pep-0793/shim.c
608628 :language: c
@@ -626,6 +646,10 @@ be added as a new HOWTO.
626646Example
627647=======
628648
649+ .. note ::
650+
651+ The example was updated for :pep: `820 `.
652+
629653.. literalinclude :: pep-0793/examplemodule.c
630654 :language: c
631655
@@ -693,6 +717,10 @@ These ideas are out of scope for *this* proposal.
693717Improving slots in general
694718--------------------------
695719
720+ .. note ::
721+
722+ This idea was implemented in :pep: `820 `.
723+
696724Slots -- and specifically the existing ``PyModuleDef_Slot `` -- do have a few
697725shortcomings. The most important are:
698726
0 commit comments