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