dynamic loading ALMOST works on AIX

Steven D. Majewski (sdm7g@elvis.med.virginia.edu)
Sat, 19 Feb 1994 23:24:13 -0500

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