[Python-Dev] nested extension modules?
Guido van Rossum
guido@python.org
Tue, 20 Aug 2002 12:13:50 -0400
> Using the source (Luke), I was trying to figure out the best way to add a
> nested submodule from within an extension module. I noticed that the module
> initialization code will set the module name from the package context (if
> set), altogether discarding any name passed explicitly:
>
> [modsupport.c: Py_InitModule4()]
>
> ...
> if (_Py_PackageContext != NULL) {
> char *p = strrchr(_Py_PackageContext, '.');
> if (p != NULL && strcmp(name, p+1) == 0) {
> name = _Py_PackageContext;
> _Py_PackageContext = NULL;
> }
> }
>
> This _Py_PackageContext is set up from within _PyImport_LoadDynamicModule
> [importdl.c:]
>
> ...
> oldcontext = _Py_PackageContext;
> _Py_PackageContext = packagecontext;
> (*p)();
> _Py_PackageContext = oldcontext;
>
> IIUC, this means that when an extension module is loaded as part of a
> package, any submodules I create my calling Py_InitModule<whatever> will
> come out with the same name.
>
> Questions:
>
> a. Have I got the analysis right?
Not quite, if I understand what you're saying. The package context,
despite its name, is not the package name, but the full name of the
*module*, when the shared library is found inside a package.
If, e.g., a package directory P contains an extension module file
E.so, the package context is set to "P.E". The initE() function is
supposed to call Py_InitModule4() with "E" as the module name.
Py_InitModule4() then sees that this is the last component of the
package context, and changes the module name to "P.E". It also nulls
out the package context.
The checkin comment I made back in 1997 explains this:
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).
> b. Is there a more-sanctioned way around this other than touching
> _Py_PackageContext (which seems to be intended to be private)
I think using _Py_PackageContext is your only hope. If you contribute
some docs for it we'll gladly add them to the API docs.
--Guido van Rossum (home page: http://www.python.org/~guido/)