@@ -210,6 +210,8 @@ versions you support.
210210This will ensure that nothing breaks as you are porting.
211211
212212
213+ .. _abi3t-howto-modexport :
214+
213215Module export hook
214216==================
215217
@@ -290,6 +292,104 @@ and substitute your own values.
290292See the :c:type: `PySlot ` and :c:ref: `export hook <extension-export-hook >`
291293documentation for details on this API.
292294
295+ As in the example, your ``PyModExport_ `` function should *only * return a
296+ pointer to static data.
297+ If you cannot avoid additional code, refer to the
298+ :ref: `caveats in PyModExport documentation <pymodexport-api-caveats >`.
299+
300+
301+ Existing slots
302+ --------------
303+
304+ If you have a ``Py_mod_slots `` slot, check the array it refers to.
305+ It should be a :c:type: `PyModuleDef_Slot ` array like the following:
306+
307+ .. code-block ::
308+ :class: bad
309+
310+ static PyObject *create_module(PyObject *spec, PyModuleDef *def) { ... }
311+ static int my_first_module_exec(PyObject *module) { ... }
312+ static int my_second_module_exec(PyObject *module) { ... }
313+
314+ static PyModuleDef_Slot my_slots[] = {
315+ {Py_mod_gil, Py_MOD_GIL_NOT_USED},
316+ {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
317+ {Py_mod_create, my_module_create},
318+ {Py_mod_exec, my_first_module_exec},
319+ {Py_mod_exec, my_second_module_exec},
320+ {0, NULL}
321+ };
322+
323+ ``py_mod_create ``
324+ .................
325+
326+
327+ If you have a :c:macro: `Py_mod_create ` entry, make sure the function can be
328+ called with ``NULL `` as its second argument (instead of the
329+ :c:type: `PyModuleDef `, which you are removing).
330+ Often, this argument isn't used at all; you can check by renaming it:
331+
332+ .. code-block ::
333+ :class: good
334+
335+ static PyObject *create_module(PyObject *spec, PyModuleDef *_unused) { ... }
336+
337+ If the argument is used, find a different way to pass in the data.
338+ Commonly, the information is static and you can refer to it directly.
339+ (If you're reusing a single function for several different modules, consider
340+ defining several functions instead.)
341+
342+
343+ Multiple ``py_mod_exec ``
344+ ........................
345+
346+ If you have *more than one * :c:macro: `Py_mod_exec ` entry, consolidate them:
347+ create a new function that calls the others, and replace existing slots
348+ with it.
349+
350+ .. code-block ::
351+ :class: good
352+
353+ static int my_module_exec(PyObject *module) {
354+ if (my_first_module_exec(module) < 0) return -1;
355+ if (my_second_module_exec(module) < 0) return -1;
356+ }
357+
358+ static PyModuleDef_Slot my_slots[] = {
359+ ...
360+ /* (remove other Py_mod_exec slots) */
361+ ...
362+ {Py_mod_exec, my_module_exec},
363+ {0, NULL}
364+ };
365+
366+ If the functions aren't used elsewhere, you can combine their bodies instead.
367+
368+
369+ Merging slot arrays
370+ ...................
371+
372+ Optionally, when you break compatibility with Python 3.14, you may clean up
373+ the code by moving slots into the :c:type: `PySlot ` array, and converting the
374+ definitions to :c:macro: `PySlot_DATA ` and :c:macro: `PySlot_FUNC `:
375+
376+ .. code-block ::
377+ :class: good
378+
379+ static PySlot my_slot_array[] = {
380+ ...
381+ PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED),
382+ PySlot_DATA(Py_mod_multiple_interpreters,
383+ Py_MOD_PER_INTERPRETER_GIL_SUPPORTED)
384+ PySlot_FUNC(Py_mod_create, my_module_create),
385+ PySlot_FUNC(Py_mod_exec, my_module_exec),
386+ PySlot_END
387+ };
388+
389+ If you do this, delete the original :c:type: `PyModuleDef_Slot ` array and
390+ its ``Py_mod_slots `` entry.
391+
392+
293393Associated ``PyModuleDef ``
294394--------------------------
295395
@@ -483,7 +583,7 @@ For example, if a user makes a subclass like this:
483583 class Sub (YourCustomClass ):
484584 __slots__ = (' a' , ' b' )
485585
486- then ``Py_TYPE(obj) `` is ``YourCustomClass ``, and the underlying memory may
586+ then ``Py_TYPE(obj) `` is ``Sub ``, and the underlying memory may
487587look like this:
488588
489589.. code-block :: text
0 commit comments