Narzędzia użytkownika

Narzędzia witryny


jni

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Previous revision
Next revision
Previous revision
jni [2008/04/13 00:49]
chappaai
jni [2008/04/16 23:55] (aktualna)
chappaai
Linia 1: Linia 1:
 ====== Java JNI i C++ ====== ====== Java JNI i C++ ======
 +Autor : Łukasz Mosdorf G1ISI 
 + ​--- ​
 +//​[[L.Mosdorf[eeeet]stud.elka.pw.edu.pl|Łukasz Mosdorf]] 2008/04/13 01:05//
  
-Ta strona zawiera prosty przykład zastosowania Java Native Interface. Technologia ta pozwala łączyć kod Javy z kodem pisanym ​pisanym w językach specyficznych dla danej platformy. Potrzeba łączenia Javy z C++ zachodzi np gdy +Ta strona zawiera prosty przykład zastosowania Java Native Interface. Technologia ta pozwala łączyć kod Javy z kodem pisanym w językach specyficznych dla danej platformy. Potrzeba łączenia Javy z C++ zachodzi np gdy 
   * maszyna wirtualna nie jest w stanie zapewnić nam wystarczającej szybkości obliczeń   * maszyna wirtualna nie jest w stanie zapewnić nam wystarczającej szybkości obliczeń
   * Chcemy połączyć aplikację javy z juz istniejącym kawałkiem oprogramowania napisanego w C/C++   * Chcemy połączyć aplikację javy z juz istniejącym kawałkiem oprogramowania napisanego w C/C++
Linia 8: Linia 11:
   * Utworzyć klasę (Javaclass.java),​ która deklaruje metodę natywną   * Utworzyć klasę (Javaclass.java),​ która deklaruje metodę natywną
   * skompilowac tę klasę za pomocą polecenia '​javac'​ i w ten sposób otrzymać Javaclass.class   * skompilowac tę klasę za pomocą polecenia '​javac'​ i w ten sposób otrzymać Javaclass.class
-  * uzyc javah -jni aby otrzymac plik naglowkowy, w oparciu o ktory napiszemy kod w C++ +  * uzyc javah -jni aby otrzymac plik naglowkowy, w oparciu o który ​napiszemy kod w C++ 
-  * napisac ​kod w C++ +  * napisać ​kod w C++ 
   * skompilować kod do postaci biblioteki (*.dll pod Windows, *.so pod Solarisem)   * skompilować kod do postaci biblioteki (*.dll pod Windows, *.so pod Solarisem)
   * uruchomić program Javaclass   * uruchomić program Javaclass
  
-Przykladowa ​seria polecen ​potrzebna do kompilacji przykładu na platformie Windows:+Przykładowa ​seria poleceń ​potrzebna do kompilacji przykładu na platformie Windows:
  
 <code cpp> <code cpp>
Linia 21: Linia 24:
 -I"​c:​\j2sdk1.4.2_17\include\win32"​ -LD jni_pkg_Jni.cpp -FeJni_lib.dll''​ -I"​c:​\j2sdk1.4.2_17\include\win32"​ -LD jni_pkg_Jni.cpp -FeJni_lib.dll''​
 </​code>​ </​code>​
 +
 +Jeżeli powyższe polecenia nie dzialaja, należy dodać odpowienie ścieżki do zmiennej srodowiska Windows -  PATH.
 +Polecenie cl polecam uruchamiac z konsoli Visual Studio - nie mamy wtedy problemów z wskazywaniem lokalizacji dodatkowych plików nagłówkowych i bibliotek.
  
 ===== Kod Java ===== ===== Kod Java =====
Linia 31: Linia 37:
 /**  /** 
  * Program ilustrujący Zastosowanie JNI - Java Native Interface. ​  * Program ilustrujący Zastosowanie JNI - Java Native Interface. ​
- * Kod wywołuje ​+ * Kod wywołuje ​kilka natywnych metod napisanych w cpp
  */  */
 package jni_pkg; package jni_pkg;
Linia 86: Linia 92:
 } }
 </​code>​ </​code>​
 +
  
  
Linia 172: Linia 179:
 </​code>​ </​code>​
  
 +Ciała metod natywnych znajdują się w pliku cpp pzedstawionym poniżej:
  
 +<code cpp>
 +/**
 +*Łukasz Mosdorf G1ISI
 +*Plik "​jni_pkg_Jni.cpp"​ zawierajacy definicje klasy i kilka metod natywnych ​
 +*wolanych z Javy. Załączamy plik "​jni_pkg_Jni.h"​ generowany ​
 +*przy wywolaniu polecenia javah -jni jni_pkg.Jni
 +*/
 +
 +
 +
 +#include "​jni_pkg_Jni.h"​
 +#include <​iostream>​
 +#include <​jni.h>​
 +using namespace std;
 +
 +class Lol
 +{
 +private:
 + int i;
 +public:
 + void changei(int arg)
 + {
 + i=arg;
 + cout<<"​W obiekcie Lol, zmieniono wartosc i na: "<<​i<<​endl;​
 + }
 +};
 +
 +//Prosta metoda cpp wywolywana z poziomu javy
 +//Przykład podstawowej składni metody napisanej w C++ (C) i wołanej z Javy
 +JNIEXPORT void JNICALL Java_jni_1pkg_Jni_native_1call (JNIEnv * env, jclass cls)
 +{
 + cout<<"​Najprostsza metoda c++ wywołana z javy !!"<<​endl;​
 +}
 +
 +//Metoda zmieniajaca wartosc Stringa Javy podanego jako argument ​
 +JNIEXPORT jstring JNICALL Java_jni_1pkg_Jni_change_1string (JNIEnv * env, jclass jCl, jstring inStr)
 +{
 + char buf[128];
 +    const char *str;
 +
 + /* Przeksztalcamy String javowy na ciąg bajtów*/
 + str = env->​GetStringUTFChars(inStr,​ NULL);
 +    if (str == NULL) {
 +        return NULL; // OutOfMemoryError juz rzucony
 +    }
 +
 + printf("​W metodzie cpp String: %s \n", str);
 + //​Zwalniamy obiekt aby mogl sie nim zajac juz Garbage Collector
 + env->​ReleaseStringUTFChars(inStr,​ str);
 +    //Zakladamy ze uzytkownik nie wpisze wiecej niz 127 znakow...
 +    cout<<"​Wprowadz nowego Stringa"<<​endl;​
 + scanf("​%s",​ buf);
 +    ​
 + return env->​NewStringUTF(buf);​
 +}
 +
 +//Prosta metoda sumująca tablice intów 10-elementową podana z poziomy Javy jako argument
 +JNIEXPORT jint JNICALL Java_jni_1pkg_Jni_sumArray(JNIEnv *env, jobject obj, jintArray arr)
 +{
 +    jint buf[10];
 +    jint i, sum = 0;
 + //​pobieramy tablice
 +    env->​GetIntArrayRegion(arr,​ 0, 10, buf);
 + //sumujemy
 +    for (i = 0; i < 10; i++) {
 +        sum += buf[i];
 +    }
 +    return sum;
 +}
 +
 +/*Metoda inicjalizująca obiekt lol, i zapisujaca miejsce jego alokacji w pamieci ​
 +* w polu cppObjPtr obiektu który tę metodę wywolal.
 +*/
 +JNIEXPORT jint JNICALL Java_jni_1pkg_Jni_initCppObj (JNIEnv *env , jobject jObj)
 +{
 + jfieldID fid;  //​magazynujemy id pola klasy javowej
 +
 + /* pobieramy referencje na klase obiektu jObj */
 +    jclass cls = env->​GetObjectClass(jObj);​
 +
 + /* Pobieramy ID pola klasy*/
 + fid = env->​GetFieldID(cls,​ "​cppObjPtr",​ "​I"​);​
 +    if (fid == NULL) {
 +        return (jint)1; /* nie udalo sie zdobyc id pola */
 +    }
 +
 +
 + jint ptr = env->​GetIntField(jObj,​ fid);
 + cout<<"​poczatkowa wartosc wskaznika to: "<<​(int)ptr<<​endl;​
 +
 + Lol* lol = new Lol();
 + if (!lol)
 + {
 + return (jint)1; //nie udalo sie zaalokowac
 + }
 + //zwracamy wskaznik zaalokowanego obiektu
 + env->​SetIntField(jObj,​ fid, (jint)lol);
 +
 + return (jint)0;
 +}
 +
 +
 +//Prosta metoda wywołująca metodę obiektu lol (uprzednio zaalokowanego). Metoda zmienia wartość pola obiektu
 +JNIEXPORT jint JNICALL Java_jni_1pkg_Jni_changeCppObjField (JNIEnv* env, jobject jObj, jint k)
 +{
 + /​*pzrechowujemy id pola klasy javowej*/
 + jfieldID fid;  ​
 +
 + /* pobieramy referencje na klase obiektu jObj */
 +    jclass cls = env->​GetObjectClass(jObj);​
 +
 + /* pobieramy field ID*/
 + fid = env->​GetFieldID(cls,​ "​cppObjPtr",​ "​I"​);​
 +    if (fid == NULL) {
 +        return (jint)1; /* nie udalo sie zdobyc id pola */
 +    }
 + /​*Pobieramy wskaznik na nasz obiekt (zapisany w polu klasy wywolujacej metode)*/
 + jint ptr = env->​GetIntField(jObj,​ fid);
 +
 + Lol* lol = (Lol*)ptr;
 + /​*wywolujemy metodę obiektu lol*/
 + lol->​changei(k);​
 + return 0;
 +}
 +
 +//Metoda realizujaca tzw CALLBACK, czyli wywołanie metody nalezacej do obiektu javy
 +JNIEXPORT void JNICALL Java_jni_1pkg_Jni_callMe (JNIEnv * env, jobject jObj)
 +{
 + jclass cls = env->​GetObjectClass(jObj);​
 + //​pobieramy ID metody
 +    jmethodID mid = env->​GetMethodID(cls,​ "​callback",​ "​()V"​);​
 +    if (mid == NULL) {
 +        return; // nie znaleziono metody
 +    }
 +    cout<<"​W C++, przed Callback'​iem"<<​endl;​
 +    env->​CallVoidMethod(jObj,​ mid);
 + cout<<"​W C++, po Callbacku"<<​endl;​
 +}
 +
 +JNIEXPORT jint JNICALL Java_jni_1pkg_Jni_deleteCppObj (JNIEnv * env , jobject jObj)
 +{
 + jfieldID fid;  //​magazynujemy id pola klasy javowej
 +
 + /* pobieramy referencje na klase obiektu jObj */
 +    jclass cls = env->​GetObjectClass(jObj);​
 +
 + /* Pobieramy ID pola klasy*/
 + fid = env->​GetFieldID(cls,​ "​cppObjPtr",​ "​I"​);​
 +        if (fid == NULL) {
 +        return (jint)1; /* nie udalo sie zdobyc id pola */
 +        }
 +
 +
 + jint ptr = env->​GetIntField(jObj,​ fid);
 + cout<<"​poczatkowa wartosc wskaznika na obiekt ktory usuwamy to: "<<​(int)ptr<<​endl;​
 +
 + Lol* lol = reinterpret_cast<​Lol*>​(ptr);​
 +
 + delete lol;
 + //zwracamy wskaznik zaalokowanego obiektu
 + env->​SetIntField(jObj,​ fid, (jint)0);
 +
 + return (jint)0;
 +
 +
 +}
 +</​code>​
  
  
jni.1208040588.txt.gz · ostatnio zmienione: 2008/04/13 00:49 przez chappaai