Calling Win32 API method from Java
I need to call some methods in Wininet.dll from a Java program.
I can find plenty of tutorials on how to call a new DLL that I create from Java, but I can't seem to find any tutorials on how to call an already existing DLL from Java.
I know this involves JNI, but how, exactly, do I do this? Do I need to call javah
on Wininet.h? Where do I get a copy of Wininet.h? A pointer to an existing, detailed tutorial would be sufficient.
JNA seems the industry standard of what you want, "provides Java programs easy access to native shared libraries (DLLs on Windows) without writing anything but Java code—no JNI or native code is required"
There is also Java Foreign Function Interface - example usage
If is ok for you, you could embed the JRuby interpreter and call winapi via jruby-ffi wich is a lot easier, see here, here, and here
I had to do this a little while ago. You'll need a C compiler and the Windows header files. I used mingw because it's free and I was only compiling one little file.
First you make your class. Here is an example:
package org.whatever.thingy;
public class MyClass {
// Here is a JNI method, identified by 'native'
public static native callWin32Thingy(int x, int y, boolean z);
/* At this point, normal class stuff, other methods, variables, whatever */
}
You then use one of the commands that comes in the JDK, which will automatically take your class and generate .h and .c files. The command is "javah". The method signature will look something like this:
JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy
(JNIEnv *, jclass, jint, jint, jboolean);
In the .c file, you include whatever windows headers you need, and flesh out the method.
JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy
(JNIEnv *a, jclass b, jint c, jint d, jboolean e) {
// Prep steps....
Win32MethodCallWeCareAbout(x, y, z, hWhatever);
// Cleanup stuff...
}
It's very important you don't rename the method, that's how it gets associated with your specific class.
Once you've got that, you compile those files into a DLL. Here are the commands I used for mingw, you'll have to adjust classes/paths/etc.
c:/MinGW/bin/gcc -c -Ic:/MinGW/include -I"c:/Program Files/Java/jdk1.5.0_12/include"
-I"c:/Program Files/Java/jdk1.5.0_12/include/win32" -D__int64="long long"
com_whatever_thingy_MyClass_JNIHelper.c
c:/MinGW/bin/gcc -shared -o JNIHelper.dll
com_whatever_thingy_MyClass_JNIHelper_JNIHelper.o
-Wl,--add-stdcall-alias,--kill-at,--output-def,def_file
This will produce some files, including JNIHelper.dll, which is what I named my DLL.
At this point, you're basically done. You use your Java class as normal, and it will run your Win32 code when you call the static method. All you have to do is import the library. Somewhere in your code (I put it in a static block in my class) you'll need this line:
System.loadLibrary("JNIHelper");
This will cause Java to load the library named "JNIHelper.dll" and link it into the code. It has to be somewhere in the library path that Java knows about.
That's it. It's a bunch of boilerplate, but if you're doing some simple wrapping, it's easy. If you have to deal with Java types or allocating memory, it gets worse (note: I didn't, so I don't have experience there).
There's a whole tutorial here (first I found today that looked decent, and you can find others on the web. The Wikipedia article on JNI has more info too.
Hope this helps.
One cannot directly call native libraries: this is because some arguments in methods are not supported by the Java Native Interface.
There is something called GlueGen, this will create a seperate binary which will dynamically link against your native DLL. The generated binary is compatible with the JNI and thus callable from Java.
http://en.wikipedia.org/wiki/Gluegen
To get a header-file for wininet.dll, you probably need to have the Platform SDK (or Windows SDK, newest version). You can also search the net for an online repository containing this header-file.
GlueGen will need a header-file, a ANSI C compiler, etc.
There is also a less known library called NativeCall, which doesn't require GlueGen. It already has binaries which are Java compatible. This is obviously slower, since it will load the DLL dynamically upon request from Java. I haven't used this, yet, but it sounds promising:
http://johannburkard.de/software/nativecall/