I'm using Java for a small app. It's a rewrite of an existing MFC project. There is an existing dll that I need to change to enable access from Java using JNI. All of this Java stuff is new to me, so I'm having a little trouble and feeling rather dense when I read other forum posts. In the existing dll I have a function like this:
extern "C" __declspec(dllexport) bool Create()
{
return TRUE;
}
Dumb question time. How do I properly set it up to be called by Java?
I tried this:
JNIEXPORT jboolean JNICALL Create()
{
return TRUE;
}
I'm including jni.h and everything compiles fine. However, when I call it from Java I get UnsatisfiedLinkError. I'm calling it from Java using this:
public static native boolean CreateSession();
System.load("D:\\JavaCallTest.dll");
Create();
Could someone kindly push me in the proper direction? I sincerely appreciate any help.
Thanks,
Nick
To use an arbitrary DLL from Java you usually have to create an adapting DLL with the conventions of JNI that itself loads the "target" DLL and calls the required functions. To generate the correct headers for your adapter DLL you can use the tool javah shipped with the JDK.
Java native interface (JNI) is a framework provided by java that enables java programs to call native code and vice-versa. Using JNI a java program has the capability to call the native C code.
You will need to use the Java Native Interface (JNI), which is a set of C/C++ functions that allow native code to interface with java code (i.e. receiving parameters from java function calls, returning results, etc). Write a wrapper C library that receive JNI calls and then call your external library.
DLLs are linked directly when loaded. Java code needs a jvm, so you can only provide a dll that starts a jvm and starts code there, but not all necessarily stuff fits in the dll.
You need to include the Java class name and path in your native code, for example if your native method was declared in Java as:
public class NativeCode {
public static native boolean CreateSession();
}
and the class path was (for example) com.example.NativeCode
you would declare your method in native as follows:
extern "C"
JNIEXPORT jboolean JNICALL Java_com_example_NativeCode_CreateSession(JniEnv* env, jclass clazz)
{
return JNI_TRUE;
}
All JNI methods have a JNIEnv pointer and class as their first two parameters.
A static native method still needs at least two parameters:
JNIEnv *env
jclass clazz
The function name also has to correspond the the java package structure.
JNIEXPORT jboolean JNICALL Java_com_example_CreateSession(JNIEnv *env, jclass clazz)
Ideally, you would use the javah
tool to create a header file from the java class declaring the native method and then implement the declared function prototypes.
I had a similar problem - an existing C-Codebase which i needed to access from Java. It paid off for me, to get familiar with SWIG, a tool to generate an intermediate C++ DLL (which calls the C-Code), plus Java-Code that is calling into the C++ DLL.
If you have more than just 1 function of the DLL to wrap, it might pay off to check out this tool, otherwise you'd have to get familiar with JNI...
EDIT:
It seems like your DLL is not found by the System.load()
call. You might want to try System.loadLibrary()
, but note that your DLL must then be located in the path denoted by the Java system property java.library.path
.
Also dont pass the full filename in this case, but just the filename without extension.
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