web-dev-qa-db-fra.com

Appel de la méthode API Win32 à partir de Java

Je dois appeler certaines méthodes dans Wininet.dll à partir d'un programme Java.

Je peux trouver de nombreux tutoriels sur la façon d'appeler un nouveau DLL que je crée à partir de Java, mais je n'arrive pas à trouver de tutoriels sur la façon d'appeler un DLL de Java.

Je sais que cela implique JNI, mais comment, exactement, dois-je faire cela? Dois-je appeler javah sur Wininet.h? Où puis-je obtenir une copie de Wininet.h? Un pointeur vers un didacticiel existant détaillé serait suffisant.

36
Paul Reiners
  1. JNA semble le standard de l'industrie de ce que vous voulez, "fournit Java programmes accès facile aux bibliothèques partagées natives (DLL sous Windows) sans rien écrire sauf Java — non JNI ou le code natif est requis "

  2. Il y a aussi Java Foreign Function Interface - exemple d'utilisation
    Si cela vous convient, vous pouvez incorporer l'interprète JRuby et appeler winapi via jruby-ffi ce qui est beaucoup plus facile , voir ici , ici , et ici

43
clyfe

J'ai dû le faire il y a un petit moment. Vous aurez besoin d'un compilateur C et des fichiers d'en-tête Windows. J'ai utilisé mingw car c'est gratuit et je ne compilais qu'un petit fichier.

Vous faites d'abord votre classe. Voici un exemple:

package org.whatever.thingy;

public class MyClass {
    // Here is a JNI method, identified by 'native'

    public static native callWin32Thingy(int x, int y, boolean z);

    /* At this point, normal class stuff, other methods, variables, whatever */
}

Vous utilisez ensuite l'une des commandes fournies dans le JDK, qui prend automatiquement votre classe et génère des fichiers .h et .c. La commande est "javah". La signature de la méthode ressemblera à ceci:

JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy
    (JNIEnv *, jclass, jint, jint, jboolean);

Dans le fichier .c, vous incluez tous les en-têtes Windows dont vous avez besoin et expliquez la méthode.

JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy
    (JNIEnv *a, jclass b, jint c, jint d, jboolean e) {
    // Prep steps....

    Win32MethodCallWeCareAbout(x, y, z, hWhatever);

    // Cleanup stuff...
}

Il est très important de ne pas renommer la méthode, c'est ainsi qu'elle est associée à votre classe spécifique.

Une fois que vous avez cela, vous compilez ces fichiers dans une DLL. Voici les commandes que j'ai utilisées pour mingw, vous devrez ajuster les classes/chemins/etc.

c:/MinGW/bin/gcc -c -Ic:/MinGW/include -I"c:/Program Files/Java/jdk1.5.0_12/include"
    -I"c:/Program Files/Java/jdk1.5.0_12/include/win32" -D__int64="long long"
    com_whatever_thingy_MyClass_JNIHelper.c

c:/MinGW/bin/gcc -shared -o JNIHelper.dll
    com_whatever_thingy_MyClass_JNIHelper_JNIHelper.o
    -Wl,--add-stdcall-alias,--kill-at,--output-def,def_file

Cela produira certains fichiers, y compris JNIHelper.dll, qui est ce que j'ai nommé ma DLL.

À ce stade, vous avez essentiellement terminé. Vous utilisez votre classe Java comme d'habitude, et elle exécutera votre code Win32 lorsque vous appelez la méthode statique. Tout ce que vous avez à faire est d'importer la bibliothèque. Quelque part dans votre code (je l'ai mis dans un bloc statique dans ma classe) vous aurez besoin de cette ligne:

System.loadLibrary("JNIHelper");

Cela entraînera Java pour charger la bibliothèque nommée "JNIHelper.dll" et la lier dans le code. Il doit être quelque part dans le chemin de la bibliothèque qui Java sait.

C'est tout. C'est un tas de passe-partout, mais si vous faites un emballage simple, c'est facile. Si vous devez gérer Java ou allocation de mémoire, cela empire (remarque: je ne l'ai pas fait, donc je n'ai pas d'expérience là-bas).

Il y a tout un tutoriel ici (d'abord j'ai trouvé aujourd'hui qui avait l'air décent, et vous pouvez en trouver d'autres sur le web. L'article Wikipedia sur JNI a aussi plus d'informations.

J'espère que cela t'aides.

14
MBCook

On ne peut pas appeler directement des bibliothèques natives: c'est parce que certains arguments dans les méthodes ne sont pas pris en charge par l'interface Java Native).

Il y a quelque chose appelé GlueGen, cela créera un binaire séparé qui se liera dynamiquement à votre DLL native. Le binaire généré est compatible avec le JNI et peut donc être appelé à partir de Java.

http://en.wikipedia.org/wiki/Gluegen

Pour obtenir un fichier d'en-tête pour wininet.dll, vous devez probablement avoir le Platform SDK (ou Windows SDK, la dernière version). Vous pouvez également rechercher sur le net un référentiel en ligne contenant ce fichier d'en-tête.

GlueGen aura besoin d'un fichier d'en-tête, d'un compilateur C ANSI, etc.

Il existe également une bibliothèque moins connue appelée NativeCall, qui ne nécessite pas GlueGen. Il a déjà des binaires qui sont Java compatible. C'est évidemment plus lent, car il chargera dynamiquement le DLL à la demande de Java. Je ne l'ai pas utilisé , mais cela semble prometteur:

http://johannburkard.de/software/nativecall/

3
Pindatjuh