27 votes

Appel d'une méthode de l'API Win32 à partir de Java

J'ai besoin d'appeler quelques méthodes dans Wininet.dll à partir d'un programme Java.

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

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

33voto

clyfe Points 15388
  1. JNA semble la norme industrielle de ce que vous voulez, "permet aux programmes Java d'accéder facilement aux bibliothèques partagées natives (DLL sous Windows) sans écrire autre chose que du code Java - pas de JNI ou le code natif est requis"

  2. Il y a également Interface Java Foreign Function - exemple d'utilisation
    Si cela vous convient, vous pouvez intégrer le site JRuby et appeler winapi via jruby-ffi ce qui est beaucoup plus facile, voir aquí , aquí y aquí

10voto

MBCook Points 8316

J'ai dû faire ça il y a quelques temps. Vous aurez besoin d'un compilateur C et des fichiers d'en-tête Windows. J'ai utilisé mingw parce qu'il est gratuit et que je ne compilais qu'un seul petit fichier.

D'abord, vous créez 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 avec 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 à quelque chose comme ceci :

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

Dans le fichier .c, vous incluez les en-têtes Windows dont vous avez besoin et vous étoffez 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...
}

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

Une fois que vous l'avez, 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 quelques fichiers, dont JNIHelper.dll, qui est le nom que j'ai donné à ma DLL.

A ce stade, vous avez pratiquement terminé. Vous utilisez votre classe Java comme d'habitude, et elle exécutera votre code Win32 lorsque vous appellerez 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");

Java chargera alors la bibliothèque nommée "JNIHelper.dll" et l'intégrera au code. Elle doit se trouver quelque part dans le chemin de la bibliothèque que Java connaît.

C'est tout. C'est un tas d'expressions passe-partout, mais si vous faites un simple habillage, c'est facile. Si vous devez vous occuper des types Java ou de l'allocation de mémoire, c'est pire (note : je ne l'ai pas fait, donc je n'ai pas d'expérience dans ce domaine).

Il y a un tutoriel complet aquí (le premier que j'ai trouvé aujourd'hui et qui semblait décent, et vous pouvez en trouver d'autres sur le web. Le site Wikipedia L'article sur la JNI contient également plus d'informations.

J'espère que cela vous aidera.

3voto

Pindatjuh Points 6929

Il n'est pas possible d'appeler directement les bibliothèques natives : en effet, certains arguments des méthodes ne sont pas pris en charge par l'interface native Java.

Il existe un produit appelé GlueGen, qui crée un binaire distinct qui sera lié dynamiquement à votre DLL native. Le binaire généré est compatible avec la JNI et peut donc être appelé depuis Java.

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

Pour obtenir un fichier d'en-tête pour wininet.dll, vous devez probablement disposer du Platform SDK (ou Windows SDK, version la plus récente). Vous pouvez également rechercher sur le net un dépôt 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. Elle possède déjà des binaires qui sont compatibles avec Java. Elle est évidemment plus lente, puisqu'elle chargera la DLL dynamiquement à la demande de Java. Je ne l'ai pas encore utilisée, mais elle semble prometteuse :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X