| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -100,11 +100,35 @@ For example, a module called ``spam`` would be defined like this:: | |||
| 100 | 100 | The export hook is typically the only non-\ ``static`` | |
| 101 | 101 | item defined in the module's C source. | |
| 102 | 102 | ||
| 103 | - The hook should be kept short -- ideally, one line as above. | ||
| 104 | - If you do need to use Python C API in this function, it is recommended to call | ||
| 105 | - ``PyABIInfo_Check(&abi_info, "modulename")`` first to raise an exception, | ||
| 106 | - rather than crash, in common cases of ABI mismatch. | ||
| 103 | + .. _pymodexport-api-caveats: | ||
| 107 | 104 | ||
| 105 | + The hook should be kept short. | ||
| 106 | + If it does more than ``return`` a static array, several caveats apply: | ||
| 107 | + | ||
| 108 | + - If you need to use any Python C API, it is recommended to call | ||
| 109 | + :c:func:`PyABIInfo_Check` first to raise an exception, | ||
| 110 | + rather than crash, in common cases of ABI mismatch. | ||
| 111 | + - Code in the export hook must never rely on the :term:`GIL`: | ||
| 112 | + :term:`free-threaded builds <free-threaded build>` of Python can only check | ||
| 113 | + the :c:macro:`Py_mod_gil` slot (or the lack of it) after the hook returns, | ||
| 114 | + - Similarly, the hook may be called in any subinterpreter, since the | ||
| 115 | + :c:macro:`Py_mod_multiple_interpreters` slot (or lack of it) | ||
| 116 | + is only checked after the hook returns. | ||
| 117 | + | ||
| 118 | + For example:: | ||
| 119 | + | ||
| 120 | + PyMODEXPORT_FUNC | ||
| 121 | + PyModExport_modulename(void) | ||
| 122 | + { | ||
| 123 | + if (PyABIInfo_Check(&abi_info, "modulename") < 0) { | ||
| 124 | + /* ABI mismatch. It's not safe to examine the raised exception. */ | ||
| 125 | + return NULL; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + /* use Python API (as little as possible); don't rely on GIL */ | ||
| 129 | + | ||
| 130 | + return modulename_slots; | ||
| 131 | + } | ||
| 108 | 132 | ||
| 109 | 133 | .. note:: | |
| 110 | 134 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -304,6 +304,11 @@ Importing Modules | |||
| 304 | 304 | ||
| 305 | 305 | Initialization function for a module built into the interpreter. | |
| 306 | 306 | ||
| 307 | + Note that the inittab uses "``PyInit``" | ||
| 308 | + :ref:`initialization functions <extension-pyinit>`; | ||
| 309 | + there is currently no way to include "``PyModExport_``" | ||
| 310 | + :ref:`export hooks <extension-export-hook>`. | ||
| 311 | + | ||
| 307 | 312 | ||
| 308 | 313 | .. c:function:: int PyImport_ExtendInittab(struct _inittab *newtab) | |
| 309 | 314 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -210,6 +210,8 @@ versions you support. | |||
| 210 | 210 | This will ensure that nothing breaks as you are porting. | |
| 211 | 211 | ||
| 212 | 212 | ||
| 213 | + .. _abi3t-howto-modexport: | ||
| 214 | + | ||
| 213 | 215 | Module export hook | |
| 214 | 216 | ================== | |
| 215 | 217 | ||
@@ -290,6 +292,104 @@ and substitute your own values. | |||
| 290 | 292 | See the :c:type:`PySlot` and :c:ref:`export hook <extension-export-hook>` | |
| 291 | 293 | documentation for details on this API. | |
| 292 | 294 | ||
| 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 | + | ||
| 293 | 393 | Associated ``PyModuleDef`` | |
| 294 | 394 | -------------------------- | |
| 295 | 395 | ||
@@ -483,7 +583,7 @@ For example, if a user makes a subclass like this: | |||
| 483 | 583 | class Sub(YourCustomClass): | |
| 484 | 584 | __slots__ = ('a', 'b') | |
| 485 | 585 | ||
| 486 | - then ``Py_TYPE(obj)`` is ``YourCustomClass``, and the underlying memory may | ||
| 586 | + then ``Py_TYPE(obj)`` is ``Sub``, and the underlying memory may | ||
| 487 | 587 | look like this: | |
| 488 | 588 | ||
| 489 | 589 | .. code-block:: text | |
| Back | FazBrowse Home | New Git URL |
0 commit comments