Skip to content

Commit 204d3d5

Browse files
itamarofacebook-github-bot
authored andcommitted
Add C-API to support Native Python static extension importer
Summary: A C-API to enable Native Python static extension importer See python/cpython#116146 for a discussion about upstreaming such an API. Reviewed By: drinkmorewaterr Differential Revision: D82969845 fbshipit-source-id: d722c293f29c4c414b0791220ac0e39aebb56e3e
1 parent b448cc3 commit 204d3d5

2 files changed

Lines changed: 74 additions & 18 deletions

File tree

Include/cpython/import.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,15 @@ PyAPI_FUNC(PyObject*) PyImport_ImportModuleAttr(
2828
PyAPI_FUNC(PyObject*) PyImport_ImportModuleAttrString(
2929
const char *mod_name,
3030
const char *attr_name);
31+
32+
// START META PATCH (expose C API to call a module init function for statically linked extensions)
33+
// Custom importers may use this API to initialize statically linked
34+
// extension modules directly from a spec and init function,
35+
// without needing to go through inittab
36+
PyAPI_FUNC(PyObject *)
37+
_Ci_PyImport_CreateBuiltinFromSpecAndInitfunc(
38+
PyObject *spec,
39+
PyObject* (*initfunc)(void)
40+
);
41+
42+
// END META PATCH

Python/import.c

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

2325+
2326+
// START META PATCH
2327+
static PyModInitFunction
2328+
lookup_inittab_initfunc(const struct _Py_ext_module_loader_info* info)
2329+
{
2330+
struct _inittab *found = NULL;
2331+
for (struct _inittab *p = INITTAB; p->name != NULL; p++) {
2332+
if (_PyUnicode_EqualToASCIIString(info->name, p->name)) {
2333+
found = p;
2334+
}
2335+
}
2336+
if (found == NULL) {
2337+
// not found
2338+
return NULL;
2339+
}
2340+
return (PyModInitFunction)found->initfunc;
2341+
}
2342+
2343+
2344+
23252345
static PyObject*
2326-
create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
2346+
create_builtin_ex(
2347+
PyThreadState *tstate, PyObject *name,
2348+
PyObject *spec,
2349+
PyModInitFunction initfunc)
23272350
{
23282351
struct _Py_ext_module_loader_info info;
23292352
if (_Py_ext_module_loader_info_init_for_builtin(&info, name) < 0) {
@@ -2354,24 +2377,15 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
23542377
_extensions_cache_delete(info.path, info.name);
23552378
}
23562379

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;
2380+
PyModInitFunction p0 = initfunc;
23702381
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;
2382+
p0 = lookup_inittab_initfunc(&info);
2383+
if (p0 == NULL) {
2384+
/* Cannot re-init internal module ("sys" or "builtins") */
2385+
assert(is_core_module(tstate->interp, info.name, info.path));
2386+
mod = import_add_module(tstate, info.name);
2387+
goto finally;
2388+
}
23752389
}
23762390

23772391
#ifdef Py_GIL_DISABLED
@@ -2397,6 +2411,36 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
23972411
return mod;
23982412
}
23992413

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

24012445
/*****************************/
24022446
/* the builtin modules table */

0 commit comments

Comments
 (0)