| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,6 +10,8 @@ Supported Python versions: | |||
| 10 | 10 | * Python 3.6 - 3.16 | |
| 11 | 11 | * PyPy 3.6 - 3.12 | |
| 12 | 12 | ||
| 13 | + The limited C API is only supported on CPython. | ||
| 14 | + | ||
| 13 | 15 | A C11 subset (without optional features) is required, like ``static inline`` | |
| 14 | 16 | functions: see `PEP 7 <https://www.python.org/dev/peps/pep-0007/>`_. | |
| 15 | 17 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,77 @@ | |||
| 1 | + // C extension made of two C files (extension.c and static_inline.c) to detect | ||
| 2 | + // when a pythoncapi_compat.h function is implemented without "static inline". | ||
| 3 | + | ||
| 4 | + #ifndef MODULE_NAME | ||
| 5 | + # error "MODULE_NAME macro is not set" | ||
| 6 | + #endif | ||
| 7 | + | ||
| 8 | + #include "pythoncapi_compat.h" | ||
| 9 | + | ||
| 10 | + #define _STR(NAME) #NAME | ||
| 11 | + #define STR(NAME) _STR(NAME) | ||
| 12 | + #define _CONCAT(a, b) a ## b | ||
| 13 | + #define CONCAT(a, b) _CONCAT(a, b) | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + // No method and no module exec method needed, most basic C extension | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + // Use PySlot API on Python 3.15 and newer and on limited C API 3.15 and newer | ||
| 20 | + #if (PY_VERSION_HEX >= _Py_PACK_VERSION(3, 15) \ | ||
| 21 | + && (!defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15))) | ||
| 22 | + | ||
| 23 | + PyABIInfo_VAR(abi_info); | ||
| 24 | + | ||
| 25 | + static PySlot module_slots[] = { | ||
| 26 | + PySlot_PTR_STATIC(Py_mod_abi, &abi_info), | ||
| 27 | + PySlot_PTR_STATIC(Py_mod_name, (void*)STR(MODULE_NAME)), | ||
| 28 | + PySlot_PTR_STATIC(Py_mod_state_size, 0), | ||
| 29 | + PySlot_PTR_STATIC(Py_mod_gil, Py_MOD_GIL_NOT_USED), | ||
| 30 | + {0, 0, {0}, {0}} | ||
| 31 | + }; | ||
| 32 | + | ||
| 33 | + #define EXPORT_FUNC CONCAT(PyModExport_, MODULE_NAME) | ||
| 34 | + | ||
| 35 | + PyMODEXPORT_FUNC | ||
| 36 | + EXPORT_FUNC(void) | ||
| 37 | + { | ||
| 38 | + return module_slots; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + #ifdef MS_WINDOWS | ||
| 42 | + # define INIT_FUNC CONCAT(PyInit_, MODULE_NAME) | ||
| 43 | + | ||
| 44 | + // Workaround for https://github.com/pypa/distutils/issues/387 | ||
| 45 | + // https://docs.python.org/3.16/howto/abi3t-migration.html#module-export-hook | ||
| 46 | + PyMODINIT_FUNC | ||
| 47 | + INIT_FUNC(void) | ||
| 48 | + { | ||
| 49 | + PyErr_SetString(PyExc_SystemError, | ||
| 50 | + "PyInit_* called for module with PyModExport_*"); | ||
| 51 | + return NULL; | ||
| 52 | + } | ||
| 53 | + #endif | ||
| 54 | + | ||
| 55 | + #else | ||
| 56 | + | ||
| 57 | + static struct PyModuleDef module_def = { | ||
| 58 | + PyModuleDef_HEAD_INIT, | ||
| 59 | + STR(MODULE_NAME), // m_name | ||
| 60 | + _Py_NULL, // m_doc | ||
| 61 | + 0, // m_size | ||
| 62 | + _Py_NULL, // m_methods | ||
| 63 | + _Py_NULL, // m_slots | ||
| 64 | + _Py_NULL, // m_traverse | ||
| 65 | + _Py_NULL, // m_clear | ||
| 66 | + _Py_NULL, // m_free | ||
| 67 | + }; | ||
| 68 | + | ||
| 69 | + | ||
| 70 | + #define INIT_FUNC CONCAT(PyInit_, MODULE_NAME) | ||
| 71 | + | ||
| 72 | + PyMODINIT_FUNC | ||
| 73 | + INIT_FUNC(void) | ||
| 74 | + { | ||
| 75 | + return PyModule_Create(&module_def); | ||
| 76 | + } | ||
| 77 | + #endif | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -202,6 +202,28 @@ def add_common_flags(flags, limited): | |||
| 202 | 202 | language='c++') | |
| 203 | 203 | extensions.append(ext) | |
| 204 | 204 | ||
| 205 | + # Build a C extension with two C files to detect when a pythoncapi_compat.h | ||
| 206 | + # function is implemented without "static inline". | ||
| 207 | + sources = [ | ||
| 208 | + 'extension.c', | ||
| 209 | + 'static_inline.c', | ||
| 210 | + ] | ||
| 211 | + for limited in (False, True): | ||
| 212 | + if limited and not TEST_LIMITED_C_API: | ||
| 213 | + continue | ||
| 214 | + name = 'test_pythoncapi_compat_ext' | ||
| 215 | + assert name != C_EXTENSION_PREFIX | ||
| 216 | + flags = list(COMMON_FLAGS) | ||
| 217 | + if limited: | ||
| 218 | + name += LIMITED_SUFFIX | ||
| 219 | + flags.append(limited_flag) | ||
| 220 | + flags.append(f'-DMODULE_NAME={name}') | ||
| 221 | + ext = Extension( | ||
| 222 | + name, | ||
| 223 | + sources=sources, | ||
| 224 | + extra_compile_args=flags) | ||
| 225 | + extensions.append(ext) | ||
| 226 | + | ||
| 205 | 227 | setup(name="test_pythoncapi_compat", ext_modules=extensions) | |
| 206 | 228 | ||
| 207 | 229 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,6 @@ | |||
| 1 | + // C extension made of two C files (extension.c and static_inline.c) to detect | ||
| 2 | + // when a pythoncapi_compat.h function is implemented without "static inline". | ||
| 3 | + | ||
| 4 | + #include "pythoncapi_compat.h" | ||
| 5 | + | ||
| 6 | + // No function defined, only #include "pythoncapi_compat.h" | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,17 +1,17 @@ | |||
| 1 | 1 | // Always enable assertions | |
| 2 | 2 | #undef NDEBUG | |
| 3 | 3 | ||
| 4 | + #ifndef MODULE_NAME | ||
| 5 | + # error "MODULE_NAME macro is not set" | ||
| 6 | + #endif | ||
| 7 | + | ||
| 4 | 8 | #include "pythoncapi_compat.h" | |
| 5 | 9 | #include <structmember.h> // T_SHORT, READONLY | |
| 6 | 10 | ||
| 7 | 11 | #ifdef NDEBUG | |
| 8 | 12 | # error "assertions must be enabled" | |
| 9 | 13 | #endif | |
| 10 | 14 | ||
| 11 | - #ifndef MODULE_NAME | ||
| 12 | - # error "MODULE_NAME macro is not set" | ||
| 13 | - #endif | ||
| 14 | - | ||
| 15 | 15 | #define _STR(NAME) #NAME | |
| 16 | 16 | #define STR(NAME) _STR(NAME) | |
| 17 | 17 | #define _CONCAT(a, b) a ## b | |
| Back | FazBrowse Home | New Git URL |
0 commit comments