Python dynamic loading on AIX ( with or without ILU )

Steven D. Majewski (sdm7g@virginia.edu)
Sun, 22 Jan 1995 16:54:31 -0500 (EST)

I added the dynamic loading support to Python for AIX. It doesn't
use the dl interface, but AIX's 'load' routine. Support for that
routine should be built in by default ( when _AIX is defined )
however, to use them requires some additional AIX linking magic.

The python loadable modules return their function/method entry points
via the modules init - which is the only external reference from the
module that needs to be known, however, the modules usually reference
routines in the mail python image. AIX dynamic linking requires building
the main python executable image with an export list, and the loadable
modules with an import list of names that will be resolved in the
main python image. After getting the whole thing working, I haven't
actually used it much -- I think it will take a little reorganization
to make it simple to use.

It would also be possible to build Python using the portable dl-lib
implementation, but I don't think that avoids the need for import/export
lists - if so, then there is no gain over the simpler AIX native
interface.

Someday, I'll get back to reorganizing things so this works well, and
right out of the box, but for now, here's an old note I dug out of
the archive. Update notes: The getargs problem was from linking the
wrong getargs. I think I had to put that object module on the link
command line explicitly so that the wrong one wasn't pulled out of
the libraries. And the loadable module should be built "-bM:SRE" but
the main python executable should, I think, be built "-bM:RE" -i.e.
NOT shared. ( Probably one of the things that should be dome is to pull
out more of the main module support lib into a separate sharable image. )

---| Steven D. Majewski (804-982-0831) <sdm7g@Virginia.EDU> |---
---| Computer Systems Engineer University of Virginia |---
---| Department of Molecular Physiology and Biological Physics |---
---| Box 449 Health Science Center Charlottesville,VA 22908 |---

>From sdm7g@elvis.med.Virginia.EDU
Date: Sat, 19 Feb 1994 23:24:13 -0500
From: "Steven D. Majewski" <sdm7g@elvis.med.Virginia.EDU>
To: python-list@cwi.nl
Cc: guido@cwi.nl
Subject: dynamic loading ALMOST works on AIX

The full emulation of the SunOS dlopen routines are not really
necessary for dynamic loading for Python on AIX.

Since the module's init* routine exports a method list back to
the main routine, only the address of the modules initial entry
point is needed. AIX's native 'load()' routine can return that
entry point if the module is built with a "-s initxx" switch.

I initially rebuilt Python using an emulation of SunOS's libdl,
but once I discovered this, it appeared just as easy to modify
the source of import.c to use load(), as it was to get all of
the necessary defines thru make for it to build properly.

However, once Python with support for AIX dynamic loading is
built, there are other complications in building and using
these external modules.

If the external module itself has no references external to it,
it is pretty straight-forward, but if the module requires symbols
from the main routine, then AIX requires both the main and the
loadable modules to be built symetrically sharable. The external
module must be built with a list of unresolved symbols that will
be resolved at load time by another module (an import list) and
the main routine appears to have to be built with an export list
of symbols that it exports. ( I'm not completely sure of the
necessity of the latter - it may be affected by other build options -
but that is the way it has worked for me so far! )

COPT= # whatever compiler defs were used in building Python
cc $COPT -c xxmodule.c
cc -o xxmodule.so xxmodule.o -bM:SRE -e initxx 2>&1 >externals

This produecs a list of unresolved symbols in file externals -
which must be edited:

insert an initial first line of:
#! path/python
where path is the path to the python executable.

and strip off all of the initial "."-'s before symbols.
[ There was one symbol: "NoObject" that had no leading "."
which I left alone. I'm not sure if that is the correct
step. ]
Which, for xxmodule, yields something like this:

#! ../python
newintobject
initmodule
getmoduledict
newstringobject
dictinsert
err_occurred
fatal
NoObject

This file becomes both the import and export list of symbols.
Rebuild xxmodule:

cc -o xxmodule.so xxmodule.o -bM:SRE -e initxx -bI:externals

and then rebuild the python executable with: "-bM:SRE -bE:externals"
appended to the final compile step.

[ These steps can easily be automated in the Makefile. It may be
that once a sufficiently complete set is build up, it could be
used for all modules, and the main routine would not need to be
rebuilt. I don't know if there are storage or performance
implications to doing that. ]

The above steps builds a dynamically loadable xxmodule, which ALMOST
works. Everything appears to work except function foo():

>>>import xx # the next 2 lines are debug output from my import mods.
@@ Trying to load file: ./xxmodule.o
@@ SUCCESS: ./xxmodule.o Loaded.
Trying to init module xx ... # and this line was added to xxinit()
>>>xx
[ '__name__', 'bar', 'error', 'foo', 'magic' ]
>>>xx.__name__
'xx'
>>>xx.bar
<built-in function xx.bar>
>>>xx.error
'xx.error'
>>>xx.foo
<built-in function xx.foo>
>>>xx.magic
42
>>>xx.bar() # bar() is a function that returns nothing
>>>xx.foo( 1,2 ) # foo( i, j ) SHOULD return i+j !
-1118077474
>>>xx.foo( 0 ) # wrong number of args should produce an error!
-1118077474
>>>xx.foo( -1 )
1074930620
>>>xx.foo()
1074928496
>>>xx.foo( None )
-857809408

Does anybody have a clue as to what is going wrong in
xxmodule/xx_foo/getargs ?

- Steve Majewski (804-982-0831) <sdm7g@Virginia.EDU>
- UVA Department of Molecular Physiology and Biological Physics