# Defining extension modules {#extension-modules} A C extension for CPython is a shared library (for example, a `.so` file on Linux, `.pyd` DLL on Windows), which is loadable into the Python process (for example, it is compiled with compatible compiler settings), and which exports an `export hook`{.interpreted-text role="dfn"} function (or an old-style `initialization function `{.interpreted-text role="ref"}). To be importable by default (that is, by `importlib.machinery.ExtensionFileLoader`{.interpreted-text role="py:class"}), the shared library must be available on `sys.path`{.interpreted-text role="py:attr"}, and must be named after the module name plus an extension listed in `importlib.machinery.EXTENSION_SUFFIXES`{.interpreted-text role="py:attr"}. :::: note ::: title Note ::: Building, packaging and distributing extension modules is best done with third-party tools, and is out of scope of this document. One suitable tool is Setuptools, whose documentation can be found at . :::: ## Extension export hook ::: versionadded 3.15 Support for the `PyModExport_{}`{.interpreted-text role="samp"} export hook was added in Python 3.15. The older way of defining modules is still available: consult either the `extension-pyinit`{.interpreted-text role="ref"} section or earlier versions of this documentation if you plan to support earlier Python versions. ::: The export hook must be an exported function with the following signature: For modules with ASCII-only names, the `export hook `{.interpreted-text role="ref"} must be named `PyModExport_{}`{.interpreted-text role="samp"}, with `` replaced by the module\'s name. For non-ASCII module names, the export hook must instead be named `PyModExportU_{}`{.interpreted-text role="samp"} (note the `U`), with `` encoded using Python\'s *punycode* encoding with hyphens replaced by underscores. In Python: ``` 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 ``` The export hook returns an array of `PyModuleDef_Slot`{.interpreted-text role="c:type"} entries, terminated by an entry with a slot ID of `0`. These slots describe how the module should be created and initialized. This array must remain valid and constant until interpreter shutdown. Typically, it should use `static` storage. Prefer using the `Py_mod_create`{.interpreted-text role="c:macro"} and `Py_mod_exec`{.interpreted-text role="c:macro"} slots for any dynamic behavior. The export hook may return `NULL` with an exception set to signal failure. It is recommended to define the export hook function using a helper macro: > Declare an extension module export hook. This macro: > > - specifies the `PyModuleDef_Slot*`{.interpreted-text role="c:expr"} return type, > - adds any special linkage declarations required by the platform, and > - for C++, declares the function as `extern "C"`. For example, a module called `spam` would be defined like this: ``` c PyABIInfo_VAR(abi_info); static PyModuleDef_Slot spam_slots[] = { {Py_mod_abi, &abi_info}, {Py_mod_name, "spam"}, {Py_mod_init, spam_init_function}, ... {0, NULL}, }; 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 \-- 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, rather than crash, in common cases of ABI mismatch. :::: note ::: title Note ::: 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](https://peps.python.org/pep-0489/#multiple-modules-in-one-library) section in `489`{.interpreted-text role="pep"} for details. :::: ## Multi-phase initialization 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`{.interpreted-text role="c:data"}, `Py_mod_gil`{.interpreted-text role="c:data"} and `Py_mod_multiple_interpreters`{.interpreted-text role="c:data"} influence this step. - By default, Python itself then creates the module object \-- that is, it does the equivalent of calling `~object.__new__`{.interpreted-text role="py:meth"} when creating an object. This step can be overridden using the `Py_mod_create`{.interpreted-text role="c:data"} slot. - Python sets initial module attributes like `~module.__package__`{.interpreted-text role="attr"} and `~module.__loader__`{.interpreted-text role="attr"}, and inserts the module object into `sys.modules`{.interpreted-text role="py:attr"}. - Afterwards, the module object is initialized in an extension-specific way \-- the equivalent of `~object.__init__`{.interpreted-text role="py:meth"} when creating an object, or of executing top-level code in a Python-language module. The behavior is specified using the `Py_mod_exec`{.interpreted-text role="c:data"} slot. This is called *multi-phase initialization* to distinguish it from the legacy (but still supported) `single-phase initialization `{.interpreted-text role="ref"}, where an initialization function returns a fully constructed module. ::: versionchanged 3.5 Added support for multi-phase initialization (`489`{.interpreted-text role="pep"}). ::: ## Multiple module instances By default, extension modules are not singletons. For example, if the `sys.modules`{.interpreted-text role="py:attr"} 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. Additional module instances may be created in `sub-interpreters `{.interpreted-text role="ref"} or after Python runtime reinitialization (`Py_Finalize`{.interpreted-text role="c:func"} and `Py_Initialize`{.interpreted-text role="c:func"}). In these cases, sharing Python objects between module instances would likely cause crashes or undefined behavior. To avoid such issues, each instance of an extension module should be *isolated*: changes to one instance should not implicitly affect the others, and all state owned by the module, including references to Python objects, should be specific to a particular module instance. See `isolating-extensions-howto`{.interpreted-text role="ref"} for more details and a practical guide. A simpler way to avoid these issues is `raising an error on repeated initialization `{.interpreted-text role="ref"}. All modules are expected to support `sub-interpreters `{.interpreted-text role="ref"}, or otherwise explicitly signal a lack of support. This is usually achieved by isolation or blocking repeated initialization, as above. A module may also be limited to the main interpreter using the `Py_mod_multiple_interpreters`{.interpreted-text role="c:data"} slot. ## `PyInit` function {#extension-pyinit} ::: deprecated 3.15 This functionality is `soft deprecated`{.interpreted-text role="term"}. It will not get new features, but there are no plans to remove it. ::: Instead of `PyModExport_modulename`{.interpreted-text role="c:func"}, an extension module can define an older-style `initialization function`{.interpreted-text role="dfn"} with the signature: Its name should be `PyInit_{}`{.interpreted-text role="samp"}, with `` replaced by the name of the module. For non-ASCII module names, use `PyInitU_{}`{.interpreted-text role="samp"} instead, with `` encoded in the same way as for the `export hook `{.interpreted-text role="ref"} (that is, using Punycode with underscores). If a module exports both `PyInit_{}`{.interpreted-text role="samp"} and `PyModExport_{}`{.interpreted-text role="samp"}, the `PyInit_{}`{.interpreted-text role="samp"} function is ignored. Like with `PyMODEXPORT_FUNC`{.interpreted-text role="c:macro"}, it is recommended to define the initialization function using a helper macro: > Declare an extension module initialization function. This macro: > > - specifies the `PyObject*`{.interpreted-text role="c:expr"} return type, > - adds any special linkage declarations required by the platform, and > - for C++, declares the function as `extern "C"`. Normally, the initialization function (`PyInit_modulename`) returns a `PyModuleDef`{.interpreted-text role="c:type"} instance with non-`NULL` `~PyModuleDef.m_slots`{.interpreted-text role="c:member"}. This allows Python to use `multi-phase initialization `{.interpreted-text role="ref"}. Before it is returned, the `PyModuleDef` instance must be initialized using the following function: > Ensure a module definition is a properly initialized Python object that correctly reports its type and a reference count. > > Return *def* cast to `PyObject*`, or `NULL` if an error occurred. > > Calling this function is required before returning a `PyModuleDef`{.interpreted-text role="c:type"} from a module initialization function. It should not be used in other contexts. > > Note that Python assumes that `PyModuleDef` structures are statically allocated. This function may return either a new reference or a borrowed one; this reference must not be released. > > ::: versionadded > 3.5 > ::: For example, a module called `spam` would be defined like this: ``` c static struct PyModuleDef spam_module = { .m_base = PyModuleDef_HEAD_INIT, .m_name = "spam", ... }; PyMODINIT_FUNC PyInit_spam(void) { return PyModuleDef_Init(&spam_module); } ``` ### Legacy single-phase initialization {#single-phase-initialization} ::: deprecated 3.15 Single-phase initialization is `soft deprecated`{.interpreted-text role="term"}. It is a legacy mechanism to initialize extension modules, with known drawbacks and design flaws. Extension module authors are encouraged to use multi-phase initialization instead. However, there are no plans to remove support for it. ::: In single-phase initialization, the old-style `initialization function `{.interpreted-text role="ref"} (`PyInit_modulename`) should create, populate and return a module object. This is typically done using `PyModule_Create`{.interpreted-text role="c:func"} and functions like `PyModule_AddObjectRef`{.interpreted-text role="c:func"}. Single-phase initialization differs from the `default `{.interpreted-text role="ref"} in the following ways: - Single-phase modules are, or rather *contain*, "singletons". When the module is first initialized, Python saves the contents of the module\'s `__dict__` (that is, typically, the module\'s functions and types). For subsequent imports, Python does not call the initialization function again. Instead, it creates a new module object with a new `__dict__`, and copies the saved contents to it. For example, given a single-phase module `_testsinglephase` [^1] that defines a function `sum` and an exception class `error`: ``` python >>> 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 ``` The exact behavior should be considered a CPython implementation detail. - To work around the fact that `PyInit_modulename` does not take a *spec* argument, some state of the import machinery is saved and applied to the first suitable module created during the `PyInit_modulename` call. Specifically, when a sub-module is imported, this mechanism prepends the parent package name to the name of the module. A single-phase `PyInit_modulename` function should create "its" module object as soon as possible, before any other module objects can be created. - Non-ASCII module names (`PyInitU_modulename`) are not supported. - Single-phase modules support module lookup functions like `PyState_FindModule`{.interpreted-text role="c:func"}. - The module\'s `PyModuleDef.m_slots`{.interpreted-text role="c:member"} must be NULL. [^1]: `_testsinglephase` is an internal module used in CPython\'s self-test suite; your installation may or may not include it.