Skip to content

Commit 589a03a

Browse files
encukouvstinnerkumaraditya303
authored
pythongh-140550: Initial implementation of PEP 793 – PyModExport (pythonGH-140556)
Co-authored-by: Victor Stinner <[email protected]> Co-authored-by: Kumar Aditya <[email protected]>
1 parent f2bce51 commit 589a03a

32 files changed

+1492
-234
lines changed

Doc/data/stable_abi.dat

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/exports.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
inside the Python core, they are private to the core.
1010
If in an extension module, it may be declared with
1111
external linkage depending on the platform.
12+
PyMODEXPORT_FUNC: Like PyMODINIT_FUNC, but for a slots array
1213
1314
As a number of platforms support/require "__declspec(dllimport/dllexport)",
1415
we support a HAVE_DECLSPEC_DLL macro to save duplication.
@@ -62,9 +63,9 @@
6263
/* module init functions inside the core need no external linkage */
6364
/* except for Cygwin to handle embedding */
6465
# if defined(__CYGWIN__)
65-
# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*
66+
# define _PyINIT_FUNC_DECLSPEC Py_EXPORTED_SYMBOL
6667
# else /* __CYGWIN__ */
67-
# define PyMODINIT_FUNC PyObject*
68+
# define _PyINIT_FUNC_DECLSPEC
6869
# endif /* __CYGWIN__ */
6970
# else /* Py_BUILD_CORE */
7071
/* Building an extension module, or an embedded situation */
@@ -78,9 +79,9 @@
7879
# define PyAPI_DATA(RTYPE) extern Py_IMPORTED_SYMBOL RTYPE
7980
/* module init functions outside the core must be exported */
8081
# if defined(__cplusplus)
81-
# define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject*
82+
# define _PyINIT_FUNC_DECLSPEC extern "C" Py_EXPORTED_SYMBOL
8283
# else /* __cplusplus */
83-
# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*
84+
# define _PyINIT_FUNC_DECLSPEC Py_EXPORTED_SYMBOL
8485
# endif /* __cplusplus */
8586
# endif /* Py_BUILD_CORE */
8687
# endif /* HAVE_DECLSPEC_DLL */
@@ -93,13 +94,15 @@
9394
#ifndef PyAPI_DATA
9495
# define PyAPI_DATA(RTYPE) extern Py_EXPORTED_SYMBOL RTYPE
9596
#endif
96-
#ifndef PyMODINIT_FUNC
97+
#ifndef _PyINIT_FUNC_DECLSPEC
9798
# if defined(__cplusplus)
98-
# define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject*
99+
# define _PyINIT_FUNC_DECLSPEC extern "C" Py_EXPORTED_SYMBOL
99100
# else /* __cplusplus */
100-
# define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*
101+
# define _PyINIT_FUNC_DECLSPEC Py_EXPORTED_SYMBOL
101102
# endif /* __cplusplus */
102103
#endif
103104

105+
#define PyMODINIT_FUNC _PyINIT_FUNC_DECLSPEC PyObject*
106+
#define PyMODEXPORT_FUNC _PyINIT_FUNC_DECLSPEC PyModuleDef_Slot*
104107

105108
#endif /* Py_EXPORTS_H */

Include/internal/pycore_importdl.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ typedef enum ext_module_origin {
2828
_Py_ext_module_origin_DYNAMIC = 3,
2929
} _Py_ext_module_origin;
3030

31+
struct hook_prefixes {
32+
const char *const init_prefix;
33+
const char *const export_prefix;
34+
};
35+
3136
/* Input for loading an extension module. */
3237
struct _Py_ext_module_loader_info {
3338
PyObject *filename;
@@ -40,7 +45,7 @@ struct _Py_ext_module_loader_info {
4045
* depending on if it's builtin or not. */
4146
PyObject *path;
4247
_Py_ext_module_origin origin;
43-
const char *hook_prefix;
48+
const struct hook_prefixes *hook_prefixes;
4449
const char *newcontext;
4550
};
4651
extern void _Py_ext_module_loader_info_clear(
@@ -62,7 +67,9 @@ extern int _Py_ext_module_loader_info_init_from_spec(
6267
PyObject *spec);
6368
#endif
6469

65-
/* The result from running an extension module's init function. */
70+
/* The result from running an extension module's init function.
71+
* Not used for modules defined via PyModExport (slots array).
72+
*/
6673
struct _Py_ext_module_loader_result {
6774
PyModuleDef *def;
6875
PyObject *module;
@@ -89,10 +96,11 @@ extern void _Py_ext_module_loader_result_apply_error(
8996

9097
/* The module init function. */
9198
typedef PyObject *(*PyModInitFunction)(void);
99+
typedef PyModuleDef_Slot *(*PyModExportFunction)(void);
92100
#ifdef HAVE_DYNAMIC_LOADING
93-
extern PyModInitFunction _PyImport_GetModInitFunc(
101+
extern int _PyImport_GetModuleExportHooks(
94102
struct _Py_ext_module_loader_info *info,
95-
FILE *fp);
103+
FILE *fp, PyModInitFunction *modinit, PyModExportFunction *modexport);
96104
#endif
97105
extern int _PyImport_RunModInitFunc(
98106
PyModInitFunction p0,

Include/internal/pycore_moduleobject.h

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#ifndef Py_INTERNAL_MODULEOBJECT_H
22
#define Py_INTERNAL_MODULEOBJECT_H
3+
4+
#include <stdbool.h>
5+
36
#ifdef __cplusplus
47
extern "C" {
58
#endif
@@ -16,32 +19,49 @@ extern int _PyModule_IsPossiblyShadowing(PyObject *);
1619

1720
extern int _PyModule_IsExtension(PyObject *obj);
1821

22+
typedef int (*_Py_modexecfunc)(PyObject *);
23+
1924
typedef struct {
2025
PyObject_HEAD
2126
PyObject *md_dict;
22-
PyModuleDef *md_def;
2327
void *md_state;
2428
PyObject *md_weaklist;
2529
// for logging purposes after md_dict is cleared
2630
PyObject *md_name;
31+
bool md_token_is_def; /* if true, `md_token` is the PyModuleDef */
2732
#ifdef Py_GIL_DISABLED
2833
void *md_gil;
2934
#endif
35+
Py_ssize_t md_state_size;
36+
traverseproc md_state_traverse;
37+
inquiry md_state_clear;
38+
freefunc md_state_free;
39+
void *md_token;
40+
_Py_modexecfunc md_exec; /* only set if md_token_is_def is true */
3041
} PyModuleObject;
3142

32-
static inline PyModuleDef* _PyModule_GetDef(PyObject *mod) {
33-
assert(PyModule_Check(mod));
34-
return ((PyModuleObject *)mod)->md_def;
43+
#define _PyModule_CAST(op) \
44+
(assert(PyModule_Check(op)), _Py_CAST(PyModuleObject*, (op)))
45+
46+
static inline PyModuleDef *_PyModule_GetDefOrNull(PyObject *arg) {
47+
PyModuleObject *mod = _PyModule_CAST(arg);
48+
if (mod->md_token_is_def) {
49+
return (PyModuleDef *)mod->md_token;
50+
}
51+
return NULL;
52+
}
53+
54+
static inline PyModuleDef *_PyModule_GetToken(PyObject *arg) {
55+
PyModuleObject *mod = _PyModule_CAST(arg);
56+
return mod->md_token;
3557
}
3658

3759
static inline void* _PyModule_GetState(PyObject* mod) {
38-
assert(PyModule_Check(mod));
39-
return ((PyModuleObject *)mod)->md_state;
60+
return _PyModule_CAST(mod)->md_state;
4061
}
4162

4263
static inline PyObject* _PyModule_GetDict(PyObject *mod) {
43-
assert(PyModule_Check(mod));
44-
PyObject *dict = ((PyModuleObject *)mod) -> md_dict;
64+
PyObject *dict = _PyModule_CAST(mod)->md_dict;
4565
// _PyModule_GetDict(mod) must not be used after calling module_clear(mod)
4666
assert(dict != NULL);
4767
return dict; // borrowed reference

Include/moduleobject.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,19 @@ struct PyModuleDef_Slot {
8383
#endif
8484
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15)
8585
# define Py_mod_abi 5
86+
# define Py_mod_name 6
87+
# define Py_mod_doc 7
88+
# define Py_mod_state_size 8
89+
# define Py_mod_methods 9
90+
# define Py_mod_state_traverse 10
91+
# define Py_mod_state_clear 11
92+
# define Py_mod_state_free 12
93+
# define Py_mod_token 13
8694
#endif
8795

8896

8997
#ifndef Py_LIMITED_API
90-
#define _Py_mod_LAST_SLOT 5
98+
#define _Py_mod_LAST_SLOT 13
9199
#endif
92100

93101
#endif /* New in 3.5 */
@@ -109,6 +117,13 @@ struct PyModuleDef_Slot {
109117
PyAPI_FUNC(int) PyUnstable_Module_SetGIL(PyObject *module, void *gil);
110118
#endif
111119

120+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15)
121+
PyAPI_FUNC(PyObject *) PyModule_FromSlotsAndSpec(const PyModuleDef_Slot *,
122+
PyObject *spec);
123+
PyAPI_FUNC(int) PyModule_Exec(PyObject *mod);
124+
PyAPI_FUNC(int) PyModule_GetStateSize(PyObject *mod, Py_ssize_t *result);
125+
PyAPI_FUNC(int) PyModule_GetToken(PyObject *, void **result);
126+
#endif
112127

113128
#ifndef _Py_OPAQUE_PYOBJECT
114129
struct PyModuleDef {

Include/object.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,11 @@ PyAPI_FUNC(PyObject *) PyType_GetModuleByDef(PyTypeObject *, PyModuleDef *);
839839
PyAPI_FUNC(int) PyType_Freeze(PyTypeObject *type);
840840
#endif
841841

842+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15)
843+
PyAPI_FUNC(PyObject *) PyType_GetModuleByToken(PyTypeObject *type,
844+
const void *token);
845+
#endif
846+
842847
#ifdef __cplusplus
843848
}
844849
#endif

0 commit comments

Comments
 (0)