I'm making a simple JNI test app using Eclipse on Windows. My C++ compiler is MinGW 4.6.2. Java is throwing an UnsatisfiedLinkError
when I try to invoke a function in my test DLL (the DLL itself loads without problem). I have verified that my DLL exports a "C" function with the same name as the function generated by the javah
utility.
How could trying to invoke the function possibly generate a link error? (Also, is there any way to get more detail as to what symbol isn't being found? A bald statement that there's an UnsatisfiedLinkError
is next to useless.)
package com.xyz.jsdi_test;
import java.io.File;
public class JSDI
{
public static native void func(
String str,
int i,
Integer ii,
long j /* 64 bits */,
Long jj,
byte[] b
);
public static void dummy()
{
System.out.println("JSDI.dummy()");
}
static
{
File f = new File("..\\jsdi\\bin\\jsdi.dll");
System.out.println("Preparing to load: " + f);
System.load(f.getAbsolutePath());
System.out.println("Successfully loaded: " + f);
}
javah
:...
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_xyz_jsdi_test_JSDI
* Method: func
* Signature: (Ljava/lang/String;ILjava/lang/Integer;JLjava/lang/Long;[B)V
*/
JNIEXPORT void JNICALL Java_com_xyz_jsdi_1test_JSDI_func
(JNIEnv *, jclass, jstring, jint, jobject, jlong, jobject, jbyteArray);
#ifdef __cplusplus
}
#endif
extern "C"
{
JNIEXPORT void JNICALL Java_com_xyz_jsdi_1test_JSDI_func(
JNIEnv * env,
jclass _class,
jstring str,
jint i,
jobject ii,
jlong j,
jobject jj,
jbyteArray b
)
{
// don't do anything...let's just try to get called successfully...
}
} // extern "C"
...
public static void main(String[] args)
{
JSDI.dummy(); // cause class to load, which should cause System.load() to run.
JSDI.func("hello", 0, 0, 0L, 0L, (byte[])null);
}
Preparing to load: ..\jsdi\bin\jsdi.dll
Successfully loaded: ..\jsdi\bin\jsdi.dll
JSDI.dummy()
java.lang.UnsatisfiedLinkError: com.xyz.jsdi_test.JSDI.func(Ljava/lang/String;ILjava/lang/Integer;JLjava/lang/Long;[B)V
at com.xyz.jsdi_test.JSDI.func(Native Method)
at com.xyz.jsdi_test.SimpleTest.main(SimpleTest.java:24)
SOLVED IT -- WOOO!
It turns out that MSVC prepends an underscore to the name of __stdcall
functions. MinGW does not. The Windows JVM apparently expects the '_' prefix. As soon as I prepended '_' to the function name and rebuilt with MinGW, everything worked just dandy.
eg:
JNIEXPORT void JNICALL Java_com_xyz_jsdi_1test_JSDI_func ==> _Java_com_xyz_jsdi_1test_JSDI_func
EDIT:
The --add-stdcall-underscore
feature of the dlltool
utility included with MinGW can solve this problem for you transparently. Set it up in your Makefile and you don't need to worry about having different versions of the actual source code for different compilers. See at this link.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With