Skip to content

Commit 4363e5a

Browse files
committed
gh-116146: Add new C-API to create builtin from spec and initfunc
1 parent 20d5494 commit 4363e5a

File tree

2 files changed

+66
-18
lines changed

2 files changed

+66
-18
lines changed

Include/cpython/import.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ struct _inittab {
1010
PyAPI_DATA(struct _inittab *) PyImport_Inittab;
1111
PyAPI_FUNC(int) PyImport_ExtendInittab(struct _inittab *newtab);
1212

13+
// Custom importers may use this API to initialize statically linked
14+
// extension modules directly from a spec and init function,
15+
// without needing to go through inittab
16+
PyAPI_FUNC(PyObject *)
17+
PyImport_CreateBuiltinFromSpecAndInitfunc(
18+
PyObject *spec,
19+
PyObject* (*initfunc)(void)
20+
);
21+
1322
struct _frozen {
1423
const char *name; /* ASCII encoded string */
1524
const unsigned char *code;

Python/import.c

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2322,8 +2322,27 @@ is_builtin(PyObject *name)
23222322
return 0;
23232323
}
23242324

2325+
static PyModInitFunction
2326+
lookup_inittab_initfunc(const struct _Py_ext_module_loader_info* info)
2327+
{
2328+
struct _inittab *found = NULL;
2329+
for (struct _inittab *p = INITTAB; p->name != NULL; p++) {
2330+
if (_PyUnicode_EqualToASCIIString(info->name, p->name)) {
2331+
found = p;
2332+
}
2333+
}
2334+
if (found == NULL) {
2335+
// not found
2336+
return NULL;
2337+
}
2338+
return (PyModInitFunction)found->initfunc;
2339+
}
2340+
23252341
static PyObject*
2326-
create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
2342+
create_builtin_ex(
2343+
PyThreadState *tstate, PyObject *name,
2344+
PyObject *spec,
2345+
PyModInitFunction initfunc)
23272346
{
23282347
struct _Py_ext_module_loader_info info;
23292348
if (_Py_ext_module_loader_info_init_for_builtin(&info, name) < 0) {
@@ -2354,24 +2373,15 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
23542373
_extensions_cache_delete(info.path, info.name);
23552374
}
23562375

2357-
struct _inittab *found = NULL;
2358-
for (struct _inittab *p = INITTAB; p->name != NULL; p++) {
2359-
if (_PyUnicode_EqualToASCIIString(info.name, p->name)) {
2360-
found = p;
2361-
}
2362-
}
2363-
if (found == NULL) {
2364-
// not found
2365-
mod = Py_NewRef(Py_None);
2366-
goto finally;
2367-
}
2368-
2369-
PyModInitFunction p0 = (PyModInitFunction)found->initfunc;
2376+
PyModInitFunction p0 = initfunc;
23702377
if (p0 == NULL) {
2371-
/* Cannot re-init internal module ("sys" or "builtins") */
2372-
assert(is_core_module(tstate->interp, info.name, info.path));
2373-
mod = import_add_module(tstate, info.name);
2374-
goto finally;
2378+
p0 = lookup_inittab_initfunc(&info);
2379+
if (p0 == NULL) {
2380+
/* Cannot re-init internal module ("sys" or "builtins") */
2381+
assert(is_core_module(tstate->interp, info.name, info.path));
2382+
mod = import_add_module(tstate, info.name);
2383+
goto finally;
2384+
}
23752385
}
23762386

23772387
#ifdef Py_GIL_DISABLED
@@ -2397,6 +2407,35 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
23972407
return mod;
23982408
}
23992409

2410+
static PyObject*
2411+
create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
2412+
{
2413+
return create_builtin_ex(tstate, name, spec, NULL);
2414+
}
2415+
2416+
PyObject*
2417+
PyImport_CreateBuiltinFromSpecAndInitfunc(
2418+
PyObject *spec, PyObject* (*initfunc)(void))
2419+
{
2420+
PyThreadState *tstate = _PyThreadState_GET();
2421+
2422+
PyObject *name = PyObject_GetAttrString(spec, "name");
2423+
if (name == NULL) {
2424+
return NULL;
2425+
}
2426+
2427+
if (!PyUnicode_Check(name)) {
2428+
PyErr_Format(PyExc_TypeError,
2429+
"name must be string, not %.200s",
2430+
Py_TYPE(name)->tp_name);
2431+
Py_DECREF(name);
2432+
return NULL;
2433+
}
2434+
2435+
PyObject *mod = create_builtin_ex(tstate, name, spec, initfunc);
2436+
Py_DECREF(name);
2437+
return mod;
2438+
}
24002439

24012440
/*****************************/
24022441
/* the builtin modules table */

0 commit comments

Comments
 (0)