Java Native Interface · PDF fileoder in Delphi geschrieben sein. ... sei dies MS Visual Studio oder über ein C/C++ Modul für ... Wir benötigen dazu 2 zusätzliche includes

Embed Size (px)

Citation preview

  • JNIJava Native Interface

    Tutorial

    JNI Tutorial 1 / 9

  • InhaltsverzeichnisRevisionsverzeichnis............................................................................................3Einleitung............................................................................................................4Erste Schritte.......................................................................................................5

    Die Javaklasse..................................................................................................5JNI Headergenerierung.....................................................................................5Die C++ DLL....................................................................................................7Verbindung herstellen......................................................................................8

    JNI Tutorial 2 / 9

  • Revisionsverzeichnis

    Datum Version Beschreibung Autor27.06.2007 1.0 Init. Release S. Krmling

    JNI Tutorial 3 / 9

  • EinleitungIn diesem Tutorial wollen wir uns mit JNI beschftigen. JNI (Java Native Interface) ist eine Schnittstelle die es ermglicht aus Java heraus Native Bibliotheken (libraries) anzusprechen. Die Bibliotheken knnen in z.B. in C++ oder in Delphi geschrieben sein. ber Sinn und Unsinn dieser Schnittstelle bezglich der Plattformunabhngikeit kann man sich streiten. Dies auch nicht Zweck dieses Tutorials darber eine Meinung zu bilden. Fakt ist, dass man, wenn man weiterhin Plattformunabhngig sein will und JNI benutzen will, fr jede Plattform eine passende Bibliothek mit liefern muss. D.h. unter Windows wre das in Form einer DLL (Dynamic Link Library). Unter Linux wre das eine lib.so . Ich will aber an der Stelle nicht darber philosophieren sondern zeigen, dass es einfach ist diese Schnittstelle zu benutzen und welches Potenzial sie birgt. Eins sei noch vorweg gesagt. Diese Schnittstelle ist fr Spezialaufgaben gedacht, die entweder Java nicht gut oder gar nicht lsen kann. Daher empfehle ich JNI nur zu benutzen wenn es erforderlich wird, da sich sonst die Frage stellt, ob es noch Sinn macht die Anwendung in Java zu entwickeln. Jedoch genug derlei Worte. Ich werde versuchen die Thematik in einfachen Beispielen zu veranschaulichen. Anders als in einigen anderen Tutorials, werde ich kein groes Beispiel verwenden was sich durch alle Kapitel zieht, sondern in kleinen Beispielen die auf die Situation zugeschnitten sind. Ich werde in diesem Tutorial auch nicht darauf eingehen, wie JNI unter der Haube arbeitet sondern mich darauf Beschrnken wie man es anwendet. Wer dennoch wissen mchte was intern passiert, dem lege ich die Spezifikationsdokumentation ans Herz.Technische Voraussetzung ist das Java JDK ab Version 1.4. Ich empfehle jedoch das JDK 6 zu installieren. Es sollte korrekt installiert und die Umgebungsvariablen eingerichtet sein. Ich empfehle auch das Java JDK bin Verzeichnis in die path Variable aufzunehmen. Eventuelle Benutzungshinweise bezglich einer IDE werde ich hauptschlich NetBeans 5.5.1 fr Java und Microsoft Visual Studio 2005 fr C++ benutzen. Dieses Vorgehen sollte sich in den meisten fllen nur geringfgig von anderen IDEs wie z.B. Eclipse unterscheiden. Ich empfehle jedoch unabhngig davon eine IDE zu benutzen. Da ich des weiteren an einigen Stelle vorhandene Kenntnisse in Java voraussetze und nicht weiter drauf eingehe, wenn etwas unklar ist dies im Netz nach zuschlagen. Das Openbook von Galileocomputing kann ich da empfehlen.Beispielrelevanter Quellcode ist in gelben Kstchen eingebettet.

    JNI Tutorial 4 / 9

    http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/jniTOC.htmlhttp://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/jniTOC.htmlhttp://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/jniTOC.html

  • Erste SchritteDie Schritte die ntig sind um JNI zu benutzen sind folgende:

    Die JavaklasseHier werden die Methodenrmpfe deklariert, die von Java aus aufgerufen werden. Unser erstes Beispiel sieht so aus:

    public class JniTest {public static native int getNumber();

    }

    Was sofort auffllt ist das Schlsselwort native. Dadurch legen wir fest, dass Java einen Aufruf ber JNI realisieren soll. Solche Methoden haben grundstzlich keinen Rumpf. Die Darstellung hnelt also einem Java typischen Interface mit dem Unterschied, dass dies eine Klasse und kein Interface ist. Wre die Klasse als Interface deklariert wre ein JNI Aufruf nicht mglich. Speichern nicht vergessen ;-) .Jetzt muss die Javaklasse kompiliert werden. Dies kann man selbst in der Kommandozeile tun oder wenn man sich eine IDE (Eclipse, NetBeans) installiert hat darber tun. In NetBeans kann man im Projektfenster auf die Klasse rechts klicken und Compile File auswhlen. Alternativ dazu kann man auch die F9 Taste drcken. Auf der Kommandozeile sieht der Aufruf wie folgt aus:Zuerst bewegend wir uns in den Ordner wo sich die Javaklasse befindet. Dann fhren wir den Javacompiler aus mit:

    javac JniTest.java

    wenn dies Fehlerfrei ausgefhrt wurde msste sich jetzt in dem Verzeichnis wo die JniTest.java liegt eine JniTest.class befinden. Dies ist unsere compilierte Javaklasse.

    JNI HeadergenerierungAls nchstes mssen wir uns einen C++ header generieren lassen, damit wir in unserer C++ DLL den JNI Aufruf entgegennehmen knnen. Dies geschieht ausschlielich auf der Kommandozeile. Wie begeben uns auf der Kommandozeile wieder in den Ordner wo sich die java und die class Datei befinden. Dann fhren wir folgenden Befehl aus um den Header zu generieren:

    javah -o cpp_interface.h JniTest

    Erfolgt dies wieder ohne Fehler msste sich in dem Ordner jetzt zustzlich eine Datei cpp_interface.h befinden. Dieser Name des Headers ist frei whlbar.

    JNI Tutorial 5 / 9

  • Hinweis :Die Generierung des Headers kann nur ber die kompilierte Javaklasse erfolgen. Generierungsversuche auf die .java Datei hat die Meldung could not found zufolge.

    Sehen wir uns den generierten Header genauer an. Mit ganzen drumherum filtern wir uns mal eine wichtige Stelle raus. Die Methodendeklaration auf C Seite.

    JNIEXPORT jint JNICALL Java_JniTest_getNumber (JNIEnv *, jclass);

    Die Methodendeklaration wirkt auf den ersten Blick etwas Kryptisch aber es ist halb so schlimm wie es aussieht. Nehmen wir die Deklaration auseinander.jint spezifiziert den Rckgabetyp auf C Seite. Es ist ein von JNI zur Verfgung gestellter quivalenter Typ zum Javadatentyp. Der Methodenname setzt sich wie folgt zusammen. Jede JNI Methode beginnt mit Java_ gefolgt vom voll qualifizierten Klassennamen (D.h. mit kompletter Paketangabe) und dem Namen der Methode die wir in Java deklariert haben. Die Trennungspunkte des Paketpfades wurden durch Unterstriche erstetzt. D.h. wrde unter Java unsere Klasse den Paketpfad de.computerlabs unterliegen, wrde der voll qualifizierte Klassenname de.computerlabs.JniTest lauten und JNI wrde diese Methodendeklaration erstellen:

    JNIEXPORT jint JNICALL Java_de_computerlabs_JniTest_getNumber (JNIEnv *, jclass);

    Wie man gut erkennen kann wurde der komplette Paketpfad im Namen verwendet. In diesem Tutorial verzichten wir aber auf einen Paketpfad.

    Wichtig!Wenn man den Paketpfad nachtrglich ndert zieht das weitere nderungen nach sich. Java lst den Paketpfad auf dem Dateisystem als Ordnerstruktur auf. D.h. bei dem Paketpfad de.computerlabs wrde die .java datei im Quellenverzeichnis unter de/computerlabs/JniTest.java liegen. Auch der Javah Aufruf zum generieren des Headers ndert sich etwas. Statt vorher javah -o interface.h JniTest wrde dieser nun so lauten javah -o interface.h de.computerlabs.JniTest

    JNI Tutorial 6 / 9

  • Die C++ DLLJetzt machen wir uns daran den C++ Teil zu erstellen.

    Ich gehe an der Stelle jetzt nicht darauf ein, wie man die DLL erstellt. D.h. ich gehe davon aus das eine geeignete Umgebung vorhanden ist um eine C++ DLL zu erstellen, sei dies MS Visual Studio oder ber ein C/C++ Modul fr NetBeans oder Eclipse.

    Wichtig ist an der Stelle, dass (bei IDEs unter den Projekteinstellungen) zustzliche Include-Verzeichnisse (additional Include directories) eingetragen werden mssen. Im Java JDK Verzeichnis sind das include und include/win32 die hinzugefgt werden mssen. Dort befinden sich Headerdateien, u.a. jni.h, die Klassen und Strukturen bereitstellen um auf der C Seite mit Java kommunizieren zu knnen. Als nchstes binden wir den von JNI erstellten Header ein. Ist das getan, erstellen wir eine neue c++ Datei. Dort wollen wir die Methode implementieren. Wir bentigen dazu 2 zustzliche includes. Einmal die JNI.h und unsere interface.h. Den Methodenrumpf kopieren wir fast 1 zu 1 aus dem Header. Nur entfernen wir das Semikolon und schreiben stattdessen die geschweiften Klammern {}. Als einzige Anweisung geben wir einfach eine 10 zurck. Damit msste es jetzt wie folgt in der C++ Datei aussehen.

    #include "stdafx.h"#include #include "interface .h"BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){ return TRUE;}

    JNIEXPORT jint JNICALL Java_JniTest_getNumber (JNIEnv * pEnv, jclass clazz){ return 10;}

    Damit ist es jetzt auch schon getan. Jetzt muss die DLL nur noch gebaut werden. Ist das getan mssen wir die DLL jetzt in Java einbinden, damit Java sie aufrufen kann. Wir benennen die DLL nachtrglich in JNITestNative.DLL um, damit im folgenden keine Missverstndnisse bei der Bezeichnung entstehen.

    JNI Tutorial 7 / 9

  • Verbindung herstellenNachdem wir die DLL erstellt haben, mssen w