InOnIt.com
Cygwin/Java
FAQ
Calling C from Java
Organizing for JNI
Writing the HelloWorld class
Creating a .h file
Writing the C function
Loading the DLL into the JVM
Running the program
Starting a JVM from C
MLS Playoff Odds
World Football Rankings & World Cup Odds
NCAA Basketball Ratings
Hearts
Personal Home Pages
David's Company

Writing, Compiling, and Linking The C Function

For convenience, I'm putting the HelloWorld.c file in the same directory as HelloWorld.h (and HelloWorld.java). You can set things up a different way if you have conventions for this sort of thing.

We need to #include the C header file generated in the last step. Since I've got mine in the same directory as my C source file, I can use the double-quote form of #include. Making sure that we match the function prototype from the header file, we'll code the appropriate C function using the venerable printf from stdio.h:


#include <stdio.h>

#include "HelloWorld.h"

JNIEXPORT void JNICALL Java_example_jni_HelloWorld_writeHelloWorldToStdout(JNIEnv *env, jclass c)
{
	printf("Hello World!");
}

Now, we need to compile and link this example into a DLL. You can do this directly with gcc:

gcc -mno-cygwin -I$jdk/include -I$jdk/include/win32 -Wl,--add-stdcall-alias -shared -o HelloWorld.dll HelloWorld.c
Compiling with the -mno-cygwin option enables us to build DLL files which are not dependent upon the Cygwin DLL (and thus cannot make use of its APIs). We have specified two include directories from the JDK distribution, which bring in jni.h (which is at the top of our generated header file). The -shared option causes the compiler to generate a DLL rather than an executable. The -Wl,-add-stdcall-alias passes the --add-stdcall-alias option to the linker. Chuck Wilson was nice enough to let me know that I needed it; an UnsatisfiedLinkError results without it. The man page for ld says:
--add-stdcall-alias
    If given, symbols with a stdcall suffix (@nn) will be
    exported as-is and also with the suffix stripped.
... if that's helpful to you. Essentially (again, according to Chuck) this option causes gcc to emit DLLs which contain symbols both for the C calling convention and the Pascal calling convention (Windows normally uses the Pascal calling convention for DLL invocations, and so java.exe apparently does as well).

If you get an error like

HelloWorld.c:1:19: stdio.h: No such file or directory
(followed by a bunch of other errors from the JNI header files), it probably means that you are missing the gcc-mingw or mingw-runtime packages. These packages provide the headers and libraries necessary to compile Win32 programs using gcc; they support the -mno-cygwin option on Cygwin. You'll need to run the Cygwin setup program and install these packages. (They're both under the "Devel" category, among other places, in the tree.)

If you get something like:

/usr/lib/gcc-lib/i686-pc-mingw32/3.2/../../../../i686-pc-mingw32/bin/ld: cannot find -luser32
it probably means that you are missing the w32api package, which is available as part of the "Libs" category in the tree.