Thursday, June 30, 2005

I made a lot of progress today, especially in being able to call natively compiled Java classes directly from Perl code. Yesterday I wrote in this blog explaining some examples I'd come-up with which illustrated different ways one could integrate natively compiled Java with Perl. Today, I improved one of the examples and made another one irrelevant.

The two integration points that I worked on today were:

Perl -> C++ Proxy Class -> C++ SWIG Generated XS Glue -> Natively Compiled Java
-and-
Perl -> C++ SWIG Generated XS Glue -> Natively Compiled Java

If you remember, the first case was only necessary because I did not have the ability to call CNI setup functions from Perl, so I wrote a C++ Proxy Class instead to do this for me. In addition, the second case didn't even work precisely because of this CNI issue. So, today the first thing I did was set about exposing some of the CNI functions to Perl so I could avoid writing a C++ Proxy class and thus another heavy layer of indirection. Luckily it turned out to be pretty easy to get SWIG to generate Perl stubs for the three most important CNI functions: JvCreateJavaVM, JvAttachCurrentThread and JvDetachCurrentThread. The challenge in writing the SWIG interface file came in converting input data types, namely jstring (java.lang.String *), but this all worked out in the end. The interface is usable but currently not complete. In particular, I still have to account for JvVMInitArgs being passed into the JvCreateJavaVM function as well as being able to accept and use the java.lang.Thread objects being returned from JvAttachCurrentThread. Luckily these two issues are not imperative to being able to use the libgcj CNI framework and therefore work was able to progress.

After the CNI interface was in a workable state I decided to give the second case another try. I started by creating a simple Java Class, class compiling it, running gcjh on that class file to get a C++ header, then running SWIG on the header to get a XS wrapping file and a Perl Module file. The was all very simple and easily automated with a very simple Makefile. The compiling all went smoothly but when I went to run a Perl test driver I was greeted with a rather ugly stack trace and memory dump. And a message from the C Std Library telling me I was trying to 'free' a piece of memory that didn't exist. Well, I was damn sure I wasn't freeing anything in any of my code so I was able to deduce that SWIG must be doing something funky with the Java class. It turns out that SWIG generates default elements of C++ classes if they are not specified, namely a default constructors and destructors. In this default destructor SWIG was attempting to delete a pointer to a piece of memory that it hadn't created. In fact, it was trying to delete something in libgcj's garbage collected heap, and of course the OS let it know that was a No No. Luckily, there's an option in SWIG that turns the generation of default constructors and destructors off, and after I made the necessary Makefile change everything worked like a charm.

What am I going to work on tomorrow? I guess I should work on trying to complete the CNI bindings for Perl and start reading up on the Java reflection framework so I can move farther towards my dream of importing Java classes directly into Perl.

0 Comments:

Post a Comment

<< Home