Vivek
Vivek

Reputation: 2101

How to call a method in DLL in a Java program

I am trying to call a method in a DLL using JNA. So far have loaded the DLL using

Runtime.getRuntime().load("myworkspace/test.dll");

This dll contaings a method that I need to access. How can I execute the method present in DLL in my Java file. Do I create an object or something of the DLL and then get the method name after the dot operator.

Upvotes: 39

Views: 126059

Answers (2)

Rahul Tripathi
Rahul Tripathi

Reputation: 172378

From the source:

package jnahelloworldtest;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Platform;
import com.sun.jna.*;

/** Simple example of native library declaration and usage. */
public class Main {
    public interface simpleDLL extends Library {
        simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary(
            (Platform.isWindows() ? "simpleDLL" : "simpleDLLLinuxPort"), simpleDLL.class);
        // it's possible to check the platform on which program runs, for example purposes we assume that there's a linux port of the library (it's not attached to the downloadable project)
        byte giveVoidPtrGetChar(Pointer param); // char giveVoidPtrGetChar(void* param);
        int giveVoidPtrGetInt(Pointer param);   //int giveVoidPtrGetInt(void* param);
        int giveIntGetInt(int a);               // int giveIntGetInt(int a);
        void simpleCall();                      // void simpleCall();
    }

    public static void main(String[] args) {

        simpleDLL sdll = simpleDLL.INSTANCE;

        sdll.simpleCall();  // call of void function

        int a = 3;
        int result1 = sdll.giveIntGetInt(a);  // calling function with int parameter&result
        System.out.println("giveIntGetInt("+a+"): " + result1);

        String testStr = "ToBeOrNotToBe";
        Memory mTest = new Memory(testStr.length()+1);  // '+1' remember about extra byte for \0 character!
        mTest.setString(0, testStr);
        String testReturn = mTest.getString(0); // you can see that String got properly stored in Memory object
        System.out.println("String in Memory:"+testReturn);

        Memory intMem = new Memory(4);  // allocating space
        intMem.setInt(0, 666); // setting allocated memory to an integer
        Pointer intPointer = intMem.getPointer(0);

        int int1 = sdll.giveVoidPtrGetInt(Pointer.NULL); // passing null, getting default result
        System.out.println("giveVoidPtrGetInt(null):" + int1); 
        int int2 = sdll.giveVoidPtrGetInt(intMem); // passing int stored in Memory object, getting it back
       //int int2 = sdll.giveVoidPtrGetInt(intPointer);  causes JVM crash, use memory object directly!
        System.out.println("giveVoidPtrGetInt(666):" + int2);

        byte char1 = sdll.giveVoidPtrGetChar(Pointer.NULL);  // passing null, getting default result
        byte char2 = sdll.giveVoidPtrGetChar(mTest);        // passing string stored in Memory object, getting first letter

        System.out.println("giveVoidPtrGetChar(null):" + (char)char1);
        System.out.println("giveVoidPtrGetChar('ToBeOrNotToBe'):" + (char)char2);

    }
}

Upvotes: 33

Alter Reisbrei
Alter Reisbrei

Reputation: 181

Loading the DLL is only the easiest step.

As it is not really trivial to call a method of a DLL from Java this answer is only a summary of hints what you have to do to call a function from a DLL. The whole story would fill a book. And in fact there are several books about JNI (Java Native Interface).

To call a function in a native library you have to declare a method in your java class as native with the java keyword native. The declaration of this method must not have a body.

The name of the function exported from your DLL must match the following pattern: Java_classname_methodname where classname is the name of the class where you declared the native method methodname.

For example if you declare a native method private native void sayHello() in your class MyClass the name of the DLL's function would be: Java_MyClass_sayHello

Also keep in mind that the function must be exported from the DLL with the correct calling conventions JNIEXPORT and JNICALL which are defined in the header file jni.h that comes with your JDK (see include folder)

Every function of a DLL to be called from Java also must have two "hidden" arguments as first parameters (JNIEnv *env, jobject obj). env is a pointer to the calling JVM which allows you callback into the JVM and obj is the object from which the method was called.

So the whole definition of the DLL's method in our example would be: JNIEXPORT void JNICALL Java_MyClass_sayHello(JNIEnv *, jobject);

Due to these restrictions of JNI a DLL called from your code must be specifially made for your code. 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. This tool will generate the headers to be implemented from your Java code.

For further information the documentation of JNI will cover all questions about interaction with the JVM from native code. http://docs.oracle.com/javase/7/docs/technotes/guides/jni/

Upvotes: 18

Related Questions