load native lib (SWT) with JNI on windows
Ranjit Mathew
rmathew@hotmail.com
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"
to "foo_bar_Wombat.o".
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
ranlib libswt.a
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:
http://msdn.microsoft.com/library/en-us/vclang/html/_core___stdcall.asp
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?
Sincerely Yours,
Ranjit.
--
Ranjit Mathew Email: rmathew AT hotmail DOT com
Bangalore, INDIA. Web: http://ranjitmathew.tripod.com/
More information about the Java
mailing list