web-dev-qa-db-fra.com

Comment appeler une méthode dans DLL dans un programme Java

J'essaie d'appeler une méthode dans un DLL en utilisant JNA. Jusqu'à présent, j'ai chargé le DLL en utilisant

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

Cette dll contient une méthode à laquelle j'ai besoin d'accéder. Comment puis-je exécuter la méthode présente dans DLL dans mon fichier Java. Est-ce que je crée un objet ou quelque chose de la DLL = et ensuite obtenir le nom de la méthode après l’opérateur point.

29
Vivek

De la 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);

    }
}
26
Rahul Tripathi

Charger la DLL n’est que l’étape la plus simple.

Comme il n’est pas vraiment facile d’appeler une méthode de DLL de Java, cette réponse n’est qu’un résumé des astuces sur ce que vous devez faire pour appeler une fonction à partir d’une DLL. Toute l'histoire remplirait un livre. Et en fait, il existe plusieurs livres sur JNI (Java Native Interface).

Pour appeler une fonction dans une bibliothèque native, vous devez déclarer une méthode de votre classe Java comme étant native avec le mot clé Java native. La déclaration de cette méthode ne doit pas avoir de corps.

Le nom de la fonction exportée de votre DLL doit correspondre au modèle suivant: Java_classname_methodnameclassname est le nom de la classe où vous avez déclaré la méthode native methodname.

Par exemple, si vous déclarez une méthode native private native void sayHello() dans votre classe MyClass, le nom de la fonction de la DLL serait: Java_MyClass_sayHello

Notez également que la fonction doit être exportée à partir de DLL avec les conventions d'appel correctes JNIEXPORT et JNICALL définies dans le fichier d'en-tête jni.h fourni avec votre JDK (voir le dossier d'inclusion).

Chaque fonction d'un DLL à appeler depuis Java doit également avoir deux arguments "masqués" en tant que premiers paramètres (JNIEnv *env, jobject obj). env est un pointeur sur la machine virtuelle appelante qui vous permet de rappeler la machine virtuelle et obj est l'objet à partir duquel la méthode a été appelée.

Donc, la définition complète de la méthode de la DLL dans notre exemple serait: JNIEXPORT void JNICALL Java_MyClass_sayHello(JNIEnv *, jobject);

En raison de ces restrictions de JNI, un DLL appelé à partir de votre code doit être spécifiquement créé pour votre code. Pour utiliser un DLL de Java arbitraire, vous devez généralement créer un DLL d'adaptation avec les conventions de JNI qui charge lui-même la "cible" DLL et appelle les fonctions requises.

Pour générer les en-têtes corrects pour votre adaptateur DLL, vous pouvez utiliser l'outil javah fourni avec le JDK. Cet outil générera les en-têtes à implémenter à partir de votre code Java.

Pour plus d'informations, la documentation de JNI couvre toutes les questions relatives à l'interaction avec la machine virtuelle Java à partir du code natif. http://docs.Oracle.com/javase/7/docs/technotes/guides/jni/

11
Alter Reisbrei