kramann.info
© Guido Kramann

Login: Passwort:










Informatik3
1 Vom_struct_zur_Klasse
..1.1 Vom_struct_zur_Klasse
..1.2 struct_Programm
..1.3 Klassen_Programm
..1.4 Offene_Fragen
..1.5 Historie
..1.6 Objektabstraktion
..1.7 OO_Kundenverwaltung
..1.8 Objektfaehigkeiten
..1.9 Formatierung
..1.10 Motivation
..1.11 Uebung1
..1.12 Uebung2
2 UML
..2.1 Volumenberechnung
..2.2 UML_Klassendiagramm
..2.3 Konstruktor
..2.4 Statische_Variable
3 Strings
..3.1 Klassenbibliotheken
..3.2 stringUML
..3.3 Uebung3
4 Initialisierungen
4 bluej
5 Zeiger_und_Arrays
..5.1 Zeiger
..5.2 Zeiger_und_Funktion
..5.3 Uebung4
6 Vererbung
..6.1 MesswerteUML
..6.2 MesswerteProgramm
..6.3 VererbungsProgramm
..6.4 Vector
..6.5 Uebung
7 Modifikatoren
..7.1 public_Vererbung
..7.2 protected_Vererbung
8 Listen_und_Templates
..8.1 Containertypen
....8.1.1 ListeUML
....8.1.2 ListeProgramm
..8.2 Templates
....8.2.1 Listentemplate
....8.2.2 STLvectorTemplate
..8.3 Uebung5
..8.4 Uebung6
..8.5 Uebung7
9 Java
..9.1 Uebung
..9.2 GettingStarted
..9.3 Animation
..9.4 Hybrid
..9.5 Threads
10 Delegation
11 LayoutProjekt
12 Fenster
13 Uebung
14 Zwischenprojekt
..14.1 Befehle
..14.2 Planung
..14.3 JNI
..14.4 JNIumsetzen
..14.5 Anwendungsklasse
..14.6 GUI01
..14.7 GUI02
15 Rasterlayout
..15.1 Bilder_Packages
..15.2 interfaces
..15.3 ArrayList
..15.4 clone
..15.5 Uebung
16 Nuetzliches
..16.1 Threads
..16.2 Animation
..16.3 RungeKutta
..16.4 Loesungsansatz
..16.5 Internetprogrammierung
....16.5.1 Codegenerierung
....16.5.2 PHP_Programmierung
....16.5.3 PHP_OOP
....16.5.4 Java
17 Algorithmen
..17.1 RungeKutta
..17.2 Loesungsansatz
..17.3 Evoopt
..17.4 Uebung12
..17.5 Uebung8_2014
..17.6 Ausdruecke
18 Uebung10
19 UML_ALT
..19.1 Flaechenberechnung
..19.2 UML_Flaechenberechnung
..19.3 Implementierung
..19.4 ListeUML
..19.5 ListenImplementierung
..19.6 Anwendung

14.4 Umsetzung mit JNI / Kommunikation mit Java

14.4 Implementation with JNI / communication with Java (EN google-translate)

14.4 Implementacja za pomocą JNI / komunikacja z Javą (PL google-translate)

Es ist möglich Strings zwischen Java und einer Native-Funktion auszutauschen. In unserem Fall wird dann generell von Java der auszuführende Konsolenbefehl an die Native-Funktion übergeben. Diese wird stets so aufgerufen, dass eventuelle Standard- und Fehlerausgaben in die Dateien out.txt und err.txt geschrieben werden und diese dann eingelesen, zu einem einzigen String zusammengefasst und an Java zurückgegeben werden.

It is possible to exchange strings between Java and a native function. In our case, then generally of Java is the console command to be executed to the Pass native function. This is always called so that a Standard and error outputs are written to the out.txt and err.txt files and these are then read in, combined into a single string and sent to Java be returned.

Istnieje możliwość wymiany łańcuchów między Javą a natywną funkcją. W naszym przypadku, to zwykle z Java, polecenie konsoli do wykonania na Przekazać natywną funkcję. To jest zawsze nazywane tak, że każ Wyjścia standardowe i błędy są zapisywane w plikach out.txt i err.txt oraz następnie są one odczytywane, łączone w jeden ciąg i wysyłane do Javy być zwrócone.

generalcall Umsetzung mit JNI

generalcall implementation with JNI

ogólne wdrożenie z JNI

Im folgenden werden die hierzu notwendigen Schritte durchgegangen.

In the following the necessary steps are gone through.

Poniżej opisano niezbędne kroki.

1. Schreiben und Kompilieren der Wrapper-Class in Java, die die Native-Funktion aufrufen soll:
1. Write and compile the wrapper class in Java to call the Native function:
1. Napisz i skompiluj klasę opakowania w Javie, aby wywołać funkcję Native:
//Zur später leichteren Einbettung in größere Java-Programme, wird
//das hier entstehende Programm in einem Package organisiert.
//D.h. es muss ein Ordner nativ existieren und in ihm ein Ordner generalcall
//Kompiliert wird oberhalb des Ordners nativ mit dem Befehl:
//javac javac nativ/generalcall/Generalcall.java 

package nativ.generalcall; 

public class Generalcall
{
    static 
    {
        //Laden der dynamischen Bibliothek von /mnt-system.
        //Die dynamische Bibliothek muß vorher dorthin kopiert worden sein! 
        System.load("/mnt-system/fhb_knoppix/start_skripte/Generalcall.so");
    }
    public static native String generalcall(String befehl);
}

Code 14.4-1: Generalcall - Java-Wrapper-Class zu generalcall.c (siehe weiter unten).

2. Schablone für die C-Header-Datei erzeugen:
2. Create a template for the C header file:
2. Utwórz szablon dla pliku nagłówkowego C:
/opt/jdk1.7.0/bin/javah -jni -o ./nativ/generalcall/Generalcall.h nativ.generalcall.Generalcall

Code 14.4-2: Schablone für die C-Header-Datei erzeugen.

Es entsteht hierdurch folgende C-Header-Datei, die nicht von Hand geändert werden darf: Der komplizierte Funktionsname und die Namen der Übergabeparameter folgen einem Schema, das es der JVM erlaubt zu erkennen, welchem Package und welcher Java-Klasse die Native-Methode zugeordnet ist.

This results in the following C header file, which must not be changed by hand: The complicated function name and the names of the transfer parameters follow a scheme, which allows the JVM to recognize which package and which Java class the Native method assigned.

W wyniku tego powstanie następujący plik nagłówkowy C, którego nie można zmieniać ręcznie: Skomplikowana nazwa funkcji i nazwy parametrów transferu są zgodne ze schematem, co pozwala JVM rozpoznać, który pakiet i która klasa Java jest metodą macierzystą jest przypisany.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class nativ_generalcall_Generalcall */

#ifndef _Included_nativ_generalcall_Generalcall
#define _Included_nativ_generalcall_Generalcall
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     nativ_generalcall_Generalcall
 * Method:    generalcall
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_nativ_generalcall_Generalcall_generalcall
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

Code 14.4-3: Generalcall.h

3. Aus Generalcall.h Funktionskopf für selbst zu schreibenden C-Quellcode in Generalcall.c auslesen:
3. From Generalcall.h Read function header for self-written C source code in Generalcall.c:
3. Od Generalcall.h Czytaj nagłówek funkcji dla samodzielnie napisanego kodu źródłowego C w Generalcall.c:

Nun wird die Implementierung der c-Funktion Java_nativ_generalcall_Generalcall_generalcall gemäß der Header-Datei in die Datei Generalcall.c geschrieben. Die weiter oben besprochene Funktionalität wird hier umgesetzt:

Now the implementation of the c-function Java_nativ_generalcall_Generalcall_generalcall according to the Header file written in the file Generalcall.c. The functionality discussed above is implemented here:

Teraz implementacja funkcji c Java_nativ_generalcall_Generalcall_generalcall zgodnie z Plik nagłówka zapisany w pliku Generalcall.c. Funkcjonalność omówiona powyżej jest zaimplementowana tutaj:

#include<jni.h>
#include "Generalcall.h"
#include <stdlib.h>
#include <stdio.h>

JNIEXPORT jstring JNICALL Java_nativ_generalcall_Generalcall_generalcall(JNIEnv *env, jclass clazz, jstring in_befehl)                                                                   
{
    FILE* f;
    int i;
    int c;
    const char* ergaenzung = " > /mnt-system/out.txt 2> /mnt-system/err.txt";
    char *puffer1;
    char *puffer2;
    int anz,anzout,anzerr;

    //Von Java übergebenes String mit dem auszuführenden Konsolenbefehl in char* wandeln:
    const char *befehl = (*env)->GetStringUTFChars(env, in_befehl, 0);

    system(befehl);


    //Zeichenanzahl in err.txt und out.txt feststellen:
    f = fopen("/mnt-system/out.txt","r");
    c = fgetc(f);
    anzout=0;    
    while(c>=0)
    {
        //puffer[anz]=c;
        c = fgetc(f);
        anzout++;
    }
    fclose(f);    

    f = fopen("/mnt-system/err.txt","r");
    c = fgetc(f);
    anzerr=0;    
    while(c>=0)
    {
        //puffer[anz]=c;
        c = fgetc(f);
        anzerr++;
    }
    fclose(f);    

    //Speicher in passender Größe allokieren, damit die Dateien out.txt und err.txt darin Platz haben.
    //Es wird zuerst err.txt eingelesen und dann out.txt
    //Die Dateien werden durch einen klar erkennbaren Trenner unterteilt, für den auch noch Speicherplatz
    //reserviert werden muß.
    //Der Trenner heißt: !&$%#
    //Falls jemand auf die Idee käme, genau diese Zeichenfolge ausgeben zu lassen in dem Konsolenprogramm,
    //dann wäre das großes Pech.
    puffer2 = (char*)malloc((anzout+5+anzerr+1)*sizeof(char));

    //Jetzt werden die Daten in den puffer2 übertragen:    
    f = fopen("/mnt-system/out.txt","r");
    c = fgetc(f);
    anzout=0;    
    while(c>=0)
    {
        puffer2[anzout]=c;
        c = fgetc(f);
        anzout++;
    }
    fclose(f);    


    puffer2[anzout] = '!';
    puffer2[anzout+1] = '&';
    puffer2[anzout+2] = '$';
    puffer2[anzout+3] = '%';
    puffer2[anzout+4] = '#';
    f = fopen("/mnt-system/err.txt","r");
    c = fgetc(f);
    anzerr=0;    
    while(c>=0)
    {
        puffer2[anzout+5+anzerr]=c;
        c = fgetc(f);
        anzerr++;
    }
    fclose(f);    


    puffer2[anzout+5+anzerr]='';

    return (*env)->NewStringUTF(env, puffer2);  //Rückgabe an Java der Dateiinhalte von out.txt und err.txt
}

Code 14.4-4: Generalcall.c - Übernahme eines Konsolenbefehls von C, ausführen und Rückgabe der Konsolenausgaben an java als String.

Kompilieren der C-Funktion mit:

Compile the C function with:

Skompiluj funkcję C za pomocą:

  • cd /mnt-system/Z_Vorlesungen/informatik3/zwischenprojekt/nativ/generalcall
  • gcc -o Generalcall.so -shared -Wl,-soname,Generalcall.so -I/opt/jdk1.7.0/include -I/opt/jdk1.7.0/include/linux Generalcall.c -static -lc

Die entstehende Datei Generalcall.so wird dann in das Verzeichnis /mnt-system/fhb_knoppix/start_skripte/Generalcall.so kopiert, da die Wrapper-Java-Class dies so erwartet.

The resulting file Generalcall.so will then be in the directory /mnt-system/fhb_knoppix/start_skripte/Generalcall.so copied because the Wrapper Java class expects this.

Wynikowy plik Generalcall.so znajdzie się w katalogu /mnt-system/fhb_knoppix/start_skripte/Generalcall.so skopiowany, ponieważ klasa Wrapper Java oczekuje tego.

Testen des Nativ-Aufrufs mit Hilfe einer einfachen Java-Anwendung:

Testing the native call using a simple Java application:

Testowanie połączenia natywnego za pomocą prostej aplikacji Java:

import nativ.generalcall.Generalcall;

public class TestGeneralcall
{
    public static void main(String[] args)
    {
        String ergebnis = Generalcall.generalcall("avrdude -c ponyser -p m32 -P /dev/ttyS0 -v > /mnt-system/out.txt 2> /mnt-system/err.txt");
        System.out.println(ergebnis);
    }
}

Code 14.4-5: TestGeneralcall.java - liegt in der Ebene, wo auch der Ordner nativ liegt.