Skip to content

Commit 2e58ff3

Browse files
committed
Fix importing of shared libraries from inside packages.
This is a bit of a hack: when the shared library is loaded, the module name is "package.module", but the module calls Py_InitModule*() with just "module" for the name. The shared library loader squirrels away the true name of the module in _Py_PackageContext, and Py_InitModule*() will substitute this (if the name actually matches).
1 parent ee6fd1c commit 2e58ff3

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

Python/importdl.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ _PyImport_LoadDynamicModule(name, pathname, fp)
233233
#else
234234
PyObject *m, *d, *s;
235235
char funcname[258];
236+
char *lastdot, *shortname, *packagecontext;
236237
dl_funcptr p = NULL;
237238
#ifdef USE_SHLIB
238239
static struct {
@@ -252,7 +253,16 @@ _PyImport_LoadDynamicModule(name, pathname, fp)
252253
Py_INCREF(m);
253254
return m;
254255
}
255-
sprintf(funcname, FUNCNAME_PATTERN, name);
256+
lastdot = strrchr(name, '.');
257+
if (lastdot == NULL) {
258+
packagecontext = NULL;
259+
shortname = name;
260+
}
261+
else {
262+
packagecontext = name;
263+
shortname = lastdot+1;
264+
}
265+
sprintf(funcname, FUNCNAME_PATTERN, shortname);
256266
#ifdef USE_SHLIB
257267
if (fp != NULL) {
258268
int i;
@@ -519,11 +529,14 @@ _PyImport_LoadDynamicModule(name, pathname, fp)
519529
got_it:
520530
#endif
521531
if (p == NULL) {
522-
PyErr_SetString(PyExc_ImportError,
523-
"dynamic module does not define init function");
532+
PyErr_Format(PyExc_ImportError,
533+
"dynamic module does not define init function (%s)",
534+
funcname);
524535
return NULL;
525536
}
537+
_Py_PackageContext = packagecontext;
526538
(*p)();
539+
_Py_PackageContext = NULL;
527540
if (PyErr_Occurred())
528541
return NULL;
529542
if (_PyImport_FixupExtension(name, pathname) == NULL)

Python/modsupport.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ typedef extended va_double;
3939
typedef double va_double;
4040
#endif
4141

42+
/* Package context -- the full module name for package imports */
43+
char *_Py_PackageContext = NULL;
44+
4245
/* Py_InitModule4() parameters:
4346
- name is the module name
4447
- methods is the list of top-level functions
@@ -69,6 +72,13 @@ Py_InitModule4(name, methods, doc, passthrough, module_api_version)
6972
if (module_api_version != PYTHON_API_VERSION)
7073
fprintf(stderr, api_version_warning,
7174
name, PYTHON_API_VERSION, name, module_api_version);
75+
if (_Py_PackageContext != NULL) {
76+
char *p = strrchr(_Py_PackageContext, '.');
77+
if (p != NULL && strcmp(name, p+1) == 0) {
78+
name = _Py_PackageContext;
79+
_Py_PackageContext = NULL;
80+
}
81+
}
7282
if ((m = PyImport_AddModule(name)) == NULL)
7383
return NULL;
7484
d = PyModule_GetDict(m);

0 commit comments

Comments
 (0)