Suppose you are writing a Java application on the windows platform and want to make a JNI call to a C function written with Microsoft Visual Studio 6.0. Well, here’s what you would do:
The ‘native’ method declaration in Java :
public class x { public native void nativeC(); ...}
resolves in the Java runtime to a dll call to a C function with thesignature
JNIEXPORT void JNICALL Java_Cd_nativeC(JNIEnv *env,jobject obj)
and for Microsoft Visual C++ 6.0,
JNIEXPORT resolves to __declspec(dllexport) JNICALL resolves to __stdcall
However, in Microsoft Visual C++ from Visual Studio 6 (compiler version12.x), functions declared as __stdcall have decorated names, where an @n is added to the function where n is a number (corresponding to number of argument bytes). So the above function name as output by the C compiler would be Java_x_nativeC@8.
That poses a problem because you can’t say:
public native void nativeC@8();
in Java because its a syntax error (‘@’ not allowed in identifiers).
Java_x_nativeC@8 will be the external name in the DLL and when you run Java and the Java application tries to call to the native dll, you will get a Java.lang.UnsatisfiedLinkError because the runtime won’t find the function inthe dll.
The fix in VS 6.0 is to add a .DEF file to the Visual Studio link command. The .DEF file can specify exports from the C code and also provide name translation. So in this case you would have a .DEF file that looks like:
-- snip ---EXPORTS Java_x_nativeC=Java_x_nativeC@8-- end --
The linker command would be:
link /map /DLL /DEF:cfile.def cfile.obj
you can also specify the translation directory in the linker command line as:
link /DLL /EXPORT Java_x_nativeC=Java_x_nativeC@8 cfile.obj
but that form becomes clumsy if you have more than one exported nativemethod.
Another tip is that if you need to find out what the decorated names look like, you can write the C file, link it without the DEF file but with the /map option and then examine the link map to find the decorated names.