[pylucene-dev] two different JCC modules in same VM; initVM()?

Andi Vajda vajda at osafoundation.org
Mon Mar 10 18:30:13 PDT 2008


On Mon, 10 Mar 2008, Andi Vajda wrote:

> I got the multi-jcc-built-extension-in-same-process thing to work. There are 
> good news and bad news:
>
> - the good:
>   . it works :)
>
> - the bad:
>   . classpath is set once per VM, there may be some class load tricks
>     that can be played but it's not something on the radar at the moment.
>   . it requires some JCC runtime code to be included in a shared library
>     instead of a python extension (on Mac, a .dylib instead of an .so
>     bundle).
>
> Python's distutils/setuptools is not so good at knowing how to build shared 
> libraries. I talked with the person behind setuptools and he said that the 
> trunk had code to support this but he wasn't sure in what state it was in. He 
> also said that patches to this were welcome. I'm going to look at this as 
> I've hit this problem before. Supporting shared libraries between python 
> extension bundles is a good thing to have in setuptools.
>
> I think that I'm going to check-in something soon where the shared library 
> building pleasure is left to the user ;) but not making it any harder to 
> build the current, default way where the JCC runtime is statically linked 
> into the extension. Later, once I figure out the setuptools thing, I can 
> update jcc's setup.py to also build the shared library.

I just checked in the changes to support this properly.

initVM() no longer takes an env argument but still needs to be called for 
every extension being imported into the process. There is only one env per 
process and any extension can return it. The python JCCEnv type is defined 
in each extension module but from the _same_ static structure in the shared 
library and Python only initializes it once.

Sadly, the classpath additions don't seem to stick so it must be set either 
in the environment or via the classpath keyword to initVM().

I made it an error to pass in any other arguments to initVM() on any calls 
other than the first one since these would be ignored. In other words, you 
get one chance per process to start and configure the Java VM.

To try this out you need:

    - a libjcc.dylib shared library
      To build this, simply enter this in the shell after building JCC
      itself (on leopard intel mac, adapt for other platforms until I
      automate this in JCC's setup.py)

g++ -dynamiclib -install_name /Library/Python/2.5/site-packages/JCC-1.8-py2.5-macosx-10.5-i386.egg/jcc/libjcc.dylib -o libjcc.dylib build/temp.macosx-10.5-i386-2.5/jcc/sources/jcc.o build/temp.macosx-10.5-i386-2.5/jcc/sources/JCCEnv.o -undefined dynamic_lookup
cp -p libjcc.dylib /Library/Python/2.5/site-packages/JCC-1.8-py2.5-macosx-10.5-i386.egg/jcc/

      This reuses the .o files built by setup.py (they're compatible). The
      g++ statement just links two files together into libjcc.dylib in a way
      that forces using libraries to look for it in the installed jcc egg.
      You can, of course, change -install_name to suit your install or omit
      it altogether and set DYLD_LIBRARY_PATH instead (not so good for
      security).

    - build all your extensions by invoking jcc with --shared (the default is
      unchanged, shared is False)
      This tells jcc to link with libjcc.dylib instead of statically
      linking with the same JCC runtime code. Again, libjcc.dylib is expected
      to be installed into the JCC egg dir (manually).

Then, once you've got everything built and installed, call initVM() on each 
of your extension modules, passing in all relevant info into the first call 
as follows:

   >>> import os, lucene, gs
   >>> lucene.initVM(os.pathsep.join([lucene.CLASSPATH, gs.CLASSPATH]),
                     other args as needed)
   >>> gs.initVM()
   >>> lucene.Document()
   >>> gs.GoodStuff.Frob()


Andi..



More information about the pylucene-dev mailing list