load native lib (SWT) with JNI on windows
Wed Nov 20 21:55:00 GMT 2002
Ingo Bormann wrote:
> I did not find it particulary difficult to buid.
> You can simply take the swt.jar (containing the class
> files)and give it to gcj.
This is indeed a simpler approach and I tried it out last
night. In short, it doesn't work yet but we're getting
there. Read on for the gory details.
I extracted all the files in swt.jar into a folder and
created a simple script that invoked "gcj -fjni -c" on
each of the class files.
Right off the hook, I got lots of errors from gcj like
"error parsing constant pool". It turns out that the
GCJ jar tool extracts files in text mode instead of
binary mode - this was easy to fix and I'll submit a
separate patch for fixing this.
Then I ran into problems with the "Point" class in
SWT. What happened was that there's a class named
"org.eclipse.swt.graphics.Point" and there's another
class named "org.eclipse.swt.internal.win32.POINT" -
on the case insensitive Windows filesystem, the
object file names (Point.o and POINT.o) clash and one
of them is overwritten. I fixed this bit by modifying
my script to explicitly compile "foo.bar.Wombat.class"
After all the object files were created (except for
the Win32 AWT Integration classes in the package
"org.eclipse.swt.internal.awt.win32" as Ingo had
pointed out), I created libswt.a like this:
ar rcs libswt.a *.o
Now I was finally able to link my "HelloSWT" program!
However, when I tried to run it I got an UnsatisfiedLinkError
for GetVersionExW. This error had me completely off
track for a while - as if explicitly designed to thwart
the attempts of prospective JNI hackers, the
"org.eclipse.swt.internal.win32.OS" class declares
(and swt-win32-2049.dll defines) JNI methods that
have the *same name as Win32 API functions*! Ugh!
In any case, it turned out that the SWT DLL exports
JNI native methods as "_Java_foo_Bar" as opposed to
all the GCC created DLLs that I'd been working with all
the while that export JNI native methods as "Java_foo_Bar".
So I had to modify LookupJNIMethod (jni.cc) with a kludge
where it first looks for "Java_foo_Bar" and then (only
for Windows) looks for "_Java_foo_Bar".
Now when I tried to run it I got an UnsatisfiedLinkError
for IsDBCSLeadByte. After some digging around I found
out that the LookupJNIMethod was trying to look for
"[...]IsDBCSLeadByte@9" while it was exported by the
SWT DLL as "[...]IsDBCSLeadByte@12".
The SWT JNI IsDBCSLeadByte method takes a single "byte"
parameter - together with the implicit "JNIEnv *" and
"jclass *", GCJ calculates the parameters to take up
9 bytes and not 12 bytes as the function expects.
Apparently the stdcall convention uses an "@nn" suffix
for function names where "nn" is the *number of bytes
popped off the stack by the function* and not just "number
of bytes in the argument list" as the MSDN documentation
would have us believe:
So I must figure out how to do this properly before
I can proceed any further. :-(
To paraphrase Alice (to reflect Anthony's sentiments):
"It is getting grosser and grosser!" ;-)
BTW, I noticed a couple of things during this exercise:
1. GCJ searches for "JNI_OnLoad" in a loaded DLL - this
symbol has to change on Windows to use the suffix
implied by stdcall.
2. It never searches for, nor invokes, "JNI_OnUnload".
Is that because DLLs are never explicitly unloaded?
Ranjit Mathew Email: rmathew AT hotmail DOT com
Bangalore, INDIA. Web: http://ranjitmathew.tripod.com/
More information about the Java