Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Inittab note & caveats for code in the export function
  • Loading branch information
encukou committed Jun 18, 2026
commit 686adffbff54fdf5d995d6b804a50a13f0e58211
22 changes: 20 additions & 2 deletions Doc/c-api/extension-modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,29 @@ For example, a module called ``spam`` would be defined like this::
The export hook is typically the only non-\ ``static``
item defined in the module's C source.

.. _pymodexport-api-caveats:

The hook should be kept short -- ideally, one line as above.
If you do need to use Python C API in this function, it is recommended to call
``PyABIInfo_Check(&abi_info, "modulename")`` first to raise an exception,
If you need to use any Python C API, it is recommended to call
:c:func:`PyABIInfo_Check` first to raise an exception,
rather than crash, in common cases of ABI mismatch.
Also, note that in :term:`free-threaded <free threading>` builds the export

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a :term:`free-threaded build` term for this.

function may be called without the :term:`GIL` held even if the extension
specifies that the GIL is required.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify what this means? "Calling with the GIL held" sounds like the old terminology for calling without an attached thread state. If export functions just need synchronization, then let's just say that.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's really the GIL here: Py_MOD_GIL_USED (or leaving Py_mod_gil out) only takes effect when Python sees it, after the hook returns.
Agree that it's confusing (and I missed a caveat, too!)
I'll expand this.

For example::

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;
}

.. note::

Expand Down
5 changes: 5 additions & 0 deletions Doc/c-api/import.rst
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ Importing Modules

Initialization function for a module built into the interpreter.

Note that the inittab uses "``PyInit``"
:ref:`initialization functions <extension-pyinit>`;
there is currently no way to include "``PyModExport_``"
:ref:`export hooks <extension-export-hook>`.


.. c:function:: int PyImport_ExtendInittab(struct _inittab *newtab)

Expand Down
6 changes: 6 additions & 0 deletions Doc/howto/abi3t-migration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,12 @@ and substitute your own values.
See the :c:type:`PySlot` and :c:ref:`export hook <extension-export-hook>`
documentation for details on this API.

As in the example, your ``PyModExport_`` function should *only* return a
pointer to static data.
If you cannot avoid additional code, refer to the
:ref:`caveats in PyModExport documentation <pymodexport-api-caveats>`.


Existing slots
--------------

Expand Down
Loading