[Python-Dev] nested extension modules?

David Abrahams David Abrahams" <dave@boost-consulting.com
Tue, 20 Aug 2002 12:54:49 -0400


From: "Guido van Rossum" <guido@python.org>

> > 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.

I think I understood that part.

> 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".

Yeah, that's what I expected.

> It also nulls out the package context.

Oops! I missed that part. Maybe that makes my problem imaginary, except
that you go on to say...

> 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.

Hmm, my only hope for what? What I was worried about was that if I tried to
create a nested sub-extension module from within my extension module by
calling Py_InitModuleXXX() directly, its name would be forced to be the
same as that of the outer extension module. Since you pointed out that
_Py_PackageContext was being nulled out, I don't think that's much of an
issue. What issues /do/ I need to be aware of when doing this?

Thanks,
Dave


-----------------------------------------------------------
           David Abrahams * Boost Consulting
dave@boost-consulting.com * http://www.boost-consulting.com