# Definiowanie modułów rozszerzeń

Rozszerzeniem języka C dla CPython jest współdzielona biblioteka (na `.so` przykład plik w systemie Linux, `.pyd` biblioteka DLL w systemie Windows), którą można załadować do proces Pythona (na przykład skompilować z użyciem zgodnych ustawień kompilatora) i która eksportuje funkcja export hook (lub staromodną funkcja inicjalizacja :ref:` <extension-pyinit>).

Aby można było importować współdzielona biblioteka współdzieloną domyślny (czyli przez `importlib.machinery.ExtensionFileLoader` ), musi być ona dostępna w `sys.path`, a jej nazwa musi składać się z nazwy moduł i rozszerzenia wymienionego w:py:attr:importlib.machinery.EXTENSION_SUFFIXES .

Informacja

Kompilację, pakowanie i dystrybucję modułów rozszerzeń zewnętrzny wykonywać za pomocą narzędzi firm trzecich, co wykracza poza zakres niniejszego dokumentu. Jednym z odpowiednich narzędzi jest Setuptools, którego dokumentację można znaleźć pod adresem https://setuptools.pypa.io/en/latest/setuptools.html.

## Hak eksportowy przedłużacza

Dodane w wersji 3.15: wparcie Obsługa haka `PyModExport_<name>` eksportu została dodana w Python 3.15. Starszy sposób definiowania moduł jest nadal dostępny: zapoznaj się z PyInit function sekcją lub wcześniejszymi wersja tej dokumentacji, jeśli planujesz wparcie wparcie wersja Pythona.

Hak eksportowy musi być eksportowaną funkcja o następującym podpisie:

PySlot *PyModExport_modulename(void)

W przypadku modułów z nazwami zawierającymi wyłącznie znaki ASCII, parametr export hook musi mieć nazwę `PyModExport_<name>`, a ``<name>``następnie zostać zastąpiony nazwą modułu.

W przypadku nazw modułów spoza zestawu ASCII hak eksportu musi zostać nazwany `PyModExportU_<name>`(zwróć uwagę na ``U`` ), `<name>` zakodowany przy użyciu kodowania punycode języka Python, z myślnikami zastąpionymi podkreśleniami. W Python:

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

Hak eksportu zwracać tablica `PySlot` wpisów zakończoną wpisem o identyfikatorze slotu równym `0`. Sloty te opisują sposób tworzenia i inicjalizacji moduł.

Ta tablica musi ważny prawidłowa i stała do momentu zamknięcia `static` interpreter . Zazwyczaj powinna korzystać `Py_mod_create`z :c:macro:`Py_mod_exec` pamięci masowej. Preferowane jest używanie slotów i w przypadku wszelkich dynamicznych zachowanie.

Hak eksportu może zwracać `NULL` wyjątek ustawiony na sygnał awarii.

Zaleca się zdefiniowanie funkcja haka eksportu za pomocą makro pomocniczego:

PyMODEXPORT_FUNC
  Część stabilnego ABI od wersji 3.15.

  Zadeklaruj hak eksportu moduł rozszerzenia. To makro:

  - określa PySlot* typ zwracać,

  - dodaje wszelkie specjalne deklaracje połączeń wymagane przez platformę i

  - dla C++ deklaruje funkcja jako

Na przykład moduł o `spam` nazwie zostałby zdefiniowany w następujący sposób:

    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)
    {
    zwracać spam_slots;
    }

Hak eksportu jest zazwyczaj jedynym elementem innym niż `static` zdefiniowanym w kodzie źródłowym moduł C.

Hak powinien być krótki – najlepiej jeden wiersz, jak powyżej. Jeśli jednak musisz użyć API Python C API w tej funkcja, zaleca się najpierw wywołać ją, aby zgłosić rzucić wyjątek, zamiast spowodować awarię, w typowych przypadkach niezgodności ABI.

Informacja

Możliwe jest eksportowanie wielu moduł z jednej biblioteki współdzielona biblioteka poprzez zdefiniowanie wielu haków eksportu. Ich importowanie wymaga jednak użycia niestandardowego importera lub odpowiednio nazwanych kopii/linków pliku rozszerzenia, ponieważ mechanizm importu Pythona znajduje tylko funkcja odpowiadającą nazwie pliku. Szczegółowe informacje moduł można znaleźć w sekcji „Wiele modułów w jednej biblioteka”. <https://peps.python.org/pep-0489/#multiple-modules-in-one-library>`__ section in PEP 489 for details.

## Inicjalizacja wielofazowa

przetwarzanie/proces przetwarzanie tworzenia moduł rozszerzenia przebiega w kilku fazach:

- Python wyszukuje i wywołuje hak eksportu, aby uzyskać informacje o sposobie tworzenia moduł.

- Zanim zostanie wykonany jakikolwiek istotny kod, Python może określić, jakie możliwości obsługuje moduł, i dostosować środowisko lub odmówić załadowania niekompatybilnego rozszerzenia. Na ten krok wpływają sloty takie jak `Py_mod_abi` , `Py_mod_gil`i :c:data:`Py_mod_multiple_interpreters` .

- domyślny Python sam tworzy obiekt moduł – czyli wykonuje czynność odpowiadającą wywołaniu `__new__()` podczas tworzenia obiektu. Ten krok można pominąć za pomocą `Py_mod_create` slotu.

- Python ustawia początkowe atrybuty moduł, takie jak `__package__` i `__loader__`, i wstawia obiekt modułu do `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.

Zmienione w wersji 3.5: Added support for multi-phase initialization (PEP 489).

## Multiple module instances

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.

Additional module instances may be created in sub-interpreters or after Python runtime reinitialization (`Py_Finalize()` and `Py_Initialize()`). 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 Extension Modules for more details and a practical guide.

A simpler way to avoid these issues is raising an error on repeated initialization.

All modules are expected to support sub-interpreters, 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` slot.

## `PyInit` function

Soft deprecated since version 3.15: 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

  Declare an extension module initialization function. This macro:

  - specifies the PyObject* return type,

  - dodaje wszelkie specjalne deklaracje połączeń wymagane przez platformę i

  - dla C++ deklaruje funkcja jako

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)
  Część stabilnego ABI od wersji 3.5.

  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` 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.

  Dodane w wersji 3.5.

Na przykład moduł o `spam` nazwie zostałby zdefiniowany w następujący sposób:

    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

Soft deprecated since version 3.15: Single-phase initialization 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 (`PyInit_modulename`) should create, populate and return a module object. This is typically done using `PyModule_Create()` and functions like `PyModule_AddObjectRef()`.

Single-phase initialization differs from the default 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`:

      >>> 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()`.

- The module’s `PyModuleDef.m_slots` must be NULL.

[1]

`_testsinglephase` is an internal module used in CPython’s self-test suite; your installation may or may not include it.