Java Native Interface_Ueberblick
Transcrição
Java Native Interface_Ueberblick
Java Native Interface Ablauf der einzelnen Schritte zur Entwicklung einer DLL • • • • • • • • • • • • • • • Java Klasse / Programm erzeugen Java-Code schreiben Native Methode definieren Übersetzen (javac) Erzeugen der Header-Datei (javah -jni test) Erzeugen einer DLL mittels Wizard Kopieren der Java-Headerdatei Kopieren der jni.h, jni_md.h Ändern des Eintrags in der Headerdatei <jni.h> in "jni.h" Kopieren der Headerdateien in Source-Dir (drei Dateien) Einfügen des Source-Code Einfügen des Import der Java-Headerdatei Übersetzen der DLL (F7) Kopieren der DLL ins Java-Verzeichnis Grafischer Überblick 1 Beispiel 1 1) Java-Programm erstellen public class Bsp1 { // native method in the DLL public native void displayHelloHSHarz(); static { System.loadLibrary("dll1"); // dll1.dll } public static void main(String[] args) { Bsp1 app = new Bsp1(); app.displayHelloHSHarz(); System.out.println("Hier in Java"); } } 2) Erstellen der Java-Class-Datei (Bsp1.java) Aufruf auf DOS-Ebene: javac Bsp1.java Erstellt die Datei java.class 3) Erstellen der Headerdatei aus Bsp1.class Aufruf auf DOS-Ebene: javah -jni Bsp1 Erstellt aus der Datei Bsp1.class die Datei Bsp1.h Ergebnis: /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class Example1 */ #ifndef _Included_Example1 #define _Included_Example1 #ifdef __cplusplus extern "C" { #endif /* * Class: Example1 * Method: displayHelloHSHarz * Signature: ()V */ 2 JNIEXPORT void JNICALL Java_Bsp1_displayHelloHSHarz (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif Ändern von <jni.h> nach "jni.h" 4) Erstellen eines Visual Studio-Projektes (Win32-DLL) • • • • Starten des Visual Studios Aufruf eines neuen Projektes mit Shift+Strg+N Eintragen des Pfades Eintragen des Namens der Dll: „dll1“ Abbildung 1 Erzeugen einer DLL mit Visual Studio Abbildung 2 Willkommen 3 Im nächsten Fenster wird der Typ der DLLausgewählt. Abbildung 3 Typ des Programms (DLL) Quellcode in der DLL: #include "stdafx.h" #include "Bsp1.h" Abbildung 4 Quellcode Mit diesen Schritten wurde eine DLL definiert. Mit der Taste „F7“ kann man die DLL erzeugen. 4 Headerdateien Wenn man nicht den Pfad für das Include-Verzeichnis eingeben will, kopiert man am einfachsten die beiden Headerdateien ins Quellverzeichnis • jni.h • jni_md.h Headerdatei „Bsp1.h“: Die erzeugte Headerdatei „Bsp1.h“ muss aus dem Java-Verzeichnis in das C-Verzeichnis kopiert werden. 5) Einfügen der Methode in das Projekt JNIEXPORT void JNICALL Java_Bsp1_displayHelloHSHarz (JNIEnv * env, jobject obj) { puts("Hier in der DLL"); } Übersetzen mit Taste F7 bzw. F6 6) Kopieren der DLL Batch-Datei: cp.bat copy debug\*.dll 7) Starten mit Eclipse oder ä. 8) Hilfsdateien: 5 j.bat C:\Programme\Java\jdk1.6.0_24\bin\javac.exe %1 %2 %3 jh.bat C:\Programme\Java\jdk1.6.0_24\bin\javah.exe %1 %2 %3 dh.bat copy debug\*.dll jni.h jni_md.h 6 Beispiel2: Aufruf einer double-Funktion: double add(a,b); Java-Quellcode: public native double callCalc(double a, double b); static { System.loadLibrary("dll2"); } public static void main(String[] args) { Bsp2 app = new Bsp2(); double d = app.callCalc(13,5); System.out.println("d: "+d); } C++: JNIEXPORT jdouble JNICALL Java_Bsp2_callCalc (JNIEnv *env, jobject obj, jdouble a, jdouble b) { return a+b; } 7 Bsp4.java: Wertetabelle import java.io.*; import java.lang.System; public class Bsp4 { // Aufruf der Startroutine public native void callWerteTabelle(double xa, double xsw, double xe); // diese Methode wird von der DLL aufgerufen public void printXY(double x, double y) { System.err.println(" Java: x:"+x+"\ty:"+y); } public void start() { callWerteTabelle(1.0, 0.5, 10.0); } static { System.loadLibrary("dll4"); } public static void main(String[] args) { Bsp4 app = new Bsp4(); app.start(); } } Bsp4.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include "jni.h" /* Header for class Bsp4 */ #ifndef _Included_Bsp4 #define _Included_Bsp4 #ifdef __cplusplus extern "C" { #endif /* * Class: Bsp4 * Method: callWerteTabelle * Signature: (DDD)V */ JNIEXPORT void JNICALL Java_Bsp4_callWerteTabelle (JNIEnv *, jobject, jdouble, jdouble, jdouble); #ifdef __cplusplus } #endif #endif 8 C-Quellcode: #include "stdafx.h" #include "Bsp4.h" double fx(double x) { return x*x*x*x - 3.89*x*x*x + 5.66*x*x -3.6511*x + 0.8811; } // // // // Funktion erstellt eine Wertetabelle Anfangswert: xa Schrittweite: xsw Endewert: xe JNIEXPORT void JNICALL Java_Bsp4_callWerteTabelle (JNIEnv *env, jobject obj, jdouble xa, jdouble xsw, jdouble xe) { // Pointer to a java method jmethodID method_printXY; // Pointer to a java class jclass clss; double x, y; // Hilfsvariablen puts("Anfangen der Berechnung in der DLL"); // get the class clss = env->GetObjectClass(obj); // get Methode method_printXY = env->GetMethodID(clss,"printXY", "(DD)V"); if (method_printXY==NULL) { puts("ERROR beim Referenzieren der Methode print_xy"); return; } // Schleife x=xa; // Anfangswert while (x<=xe) { // Funktionswert holen y = fx(x); // Aufruf der Java-Methode env->CallVoidMethod(obj, method_printXY, x,y); // X-Wert erhöhen x+=xsw; }; puts("Ende der Berechnung"); } 9 Bsp5.java: Wertetabelle in einem Editor Abbildung 5 Wertetabelle 10 Benchmark Beispiel 6 Ergebnisse n: 1000 Zeit Java: 0 Zeit C: 0 n: 20000 Zeit Java: 0 Zeit C: 0 n: 100000 Zeit Java: 79 Zeit C: 46 n: 200000 Zeit Java: 204 Zeit C: 109 n: 1000000 Zeit Java: 1781 Zeit C: 953 n: 2000000 Zeit Java: 4578 Zeit C: 2406 n: 10000000 Zeit Java: 42391 Zeit C: 21687 n: 20000000 Zeit Java: 114329 Zeit C: 61281 11 Beispiel 7. Übergabe eines int-Arrays Java: public class Bsp7 { private int [] array = new int[4]; public native void displayArray(int[] a); public Bsp7 () { for (int i=0; i<4; i++) { array[i] = i+22; } } static { System.loadLibrary("dll7"); } public static void main(String[] args) { Bsp7 app = new Bsp7(); app.displayArray(app.array); } } C-DLL: JNIEXPORT void JNICALL Java_Bsp7_displayArray (JNIEnv *env, jobject obj, jintArray intArray) { int i, k, n; // Bestimme die Länge des Feldes jsize len = env->GetArrayLength(intArray); // Array-Objekt holen jint *intArray0 = env->GetIntArrayElements(intArray,0); // Ausgabe n = (int) len; printf("size: %d\n",n); for (i=0; i<n; i++) { k =intArray0[i]; printf("Array[ %d ] = %d\n",i,k); } } 12 Beispiel 8: java: // Aufruf der Startroutine public native void callPrintText(char[] ch); public void printString(char ch) { System.out.println("in callPrintText"); System.out.println(ch); String sStr= new String (""+ch); _editor2.append( sStr ); } void BnOk_Click() { String sStr=_editor1.getText(); char[] ch; int i, n; n = sStr.length(); ch = new char[n]; for (i=0; i<n; i++) { ch[i] = sStr.charAt(i); } _editor2.setText(""); callPrintText(ch); } C-DLL: #include "stdafx.h" #include "Bsp8.h" JNIEXPORT void JNICALL Java_Bsp8_callPrintText (JNIEnv* env, jobject obj, jcharArray cArray) { int i, k, n; char ch; // Bestimme die Länge des Feldes jsize len = env->GetArrayLength(cArray); // Array-Objekt holen jchar *charArray0 = env->GetCharArrayElements(cArray,0); n = (int) len; printf("size of Array: %d\n",n); for (i=0; i<n; i++) { ch =(char) charArray0[i]; k = (int) charArray0[i]; // Ascii-Code printf("Array[ %2d ] = %c (%3d)\n",i,ch, k); } 13 for (i=0; i<n; i++) { ch =(char) charArray0[i]; k = (int) charArray0[i]; // Ascii-Code printf("%c",ch); } // Übergabe des String an Java jmethodID method_printString; // Pointer to a java class jclass clss; puts("\nAnfangen der Uebertragung an Java"); // get the class clss = env->GetObjectClass(obj); method_printString = env->GetMethodID(clss,"printString", "(C)V"); char chNew[11]; chNew[ 0]='A'; chNew[ 1]='B'; chNew[ 2]='C'; chNew[ 3]='a'; chNew[ 4]='b'; chNew[ 5]='c'; chNew[ 6]='0'; chNew[ 7]='1'; chNew[ 8]='2'; chNew[ 9]='3'; chNew[10]='!'; for (i=0; i<10; i++) { env->CallVoidMethod(obj,method_printString, chNew[i]); } env->CallVoidMethod(obj,method_printString, 13); env->CallVoidMethod(obj,method_printString, 10); for (i=0; i<10; i++) { env->CallVoidMethod(obj,method_printString, chNew[i]); } env->CallVoidMethod(obj,method_printString, 13); env->CallVoidMethod(obj,method_printString, 10); puts("Ende DLL"); } 14 Ausgabe: C:\daten\dll8>java Bsp8 size of Array: 24 Array[ 0 ] = H ( 72) Array[ 1 ] = a ( 97) Array[ 2 ] = l (108) Array[ 3 ] = l (108) Array[ 4 ] = o (111) Array[ 5 ] = ( 32) Array[ 6 ] = i (105) Array[ 7 ] = c ( 99) Array[ 8 ] = h (104) Array[ 9 ] = ( 32) Array[ 10 ] = k (107) Array[ 11 ] = o (111) Array[ 12 ] = m (109) Array[ 13 ] = m (109) Array[ 14 ] = e (101) Array[ 15 ] = ( 32) Array[ 16 ] = a ( 97) Array[ 17 ] = u (117) Array[ 18 ] = s (115) Array[ 19 ] = ( 32) Array[ 20 ] = J ( 74) Array[ 21 ] = a ( 97) Array[ 22 ] = v (118) Array[ 23 ] = a ( 97) Hallo ich komme aus Java Anfangen der Uebertragung an Java in callPrintText A in callPrintText B in callPrintText C in callPrintText a in callPrintText b in callPrintText c in callPrintText 0 in callPrintText 1 in callPrintText 2 in callPrintText 3 in callPrintText in callPrintText 15 in callPrintText A in callPrintText B in callPrintText C in callPrintText a in callPrintText b in callPrintText c in callPrintText 0 in callPrintText 1 in callPrintText 2 in callPrintText 3 in callPrintText in callPrintText Ende DLL 16