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

_______________________________________________
pylucene-dev mailing list
[email protected]
http://lists.osafoundation.org/mailman/listinfo/pylucene-dev

Reply via email to