8. diel - JNI - Pole primitívnych dátových typov
V minulom tutoriále o Java Native Interface sme si uviedli existujúci primitívne dátové typy a ako sa s nimi pracuje. Dnes si preberieme pole (Arrays) a vyskúšame si ich na príklade.
Pole primitívnych dátových typov
Práca s poľami je veľmi jednoduchá. Už nebudem krok po kroku vytvárať príklad, dúfam, že to už viete z predchádzajúcich dielov. Tu si ukážeme ako sa s takýmito poľami pracuje. Pozrime sa aká poľa môžeme v JNI používať:
Java typy - pole | Natívne JNI typy - pole | C typy - pole |
---|---|---|
boolean [] | jbooleanArray | neobsahuje |
char [] | jcharArray | char [] |
byte [] | jbyteArray | neobsahuje |
short | jshortArray | short [] |
long [] | jlongArray | long [] |
int [] | jintArray | int [] |
float [] | jfloatArray | float [] |
double [] | jdoubleArray | double [] |
public class ProjektJNIPole { private static int [] poleI1 = {5,6,12,35}; private static int [] poleI2 = {1,2,3,4}; private static double [] poleD1 = {35.56,8987.554,99.785,123.567}; native void posliPoleInt(int [] poleI1,int poleI2 []); native int [] ziskejPoleInt(); native void posliPoleDouble(double [] poleD1); native double [] ziskejPoleDouble(); public static void main(String[] args) { System.out.println("Testovaci vypis"); } }
Teraz si vykonáme vytvorenie hlavičkového súboru.
Tu je vygenerovaný header file:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class ProjektJNIPole */ #ifndef _Included_ProjektJNIPole #define _Included_ProjektJNIPole #ifdef __cplusplus extern "C" { #endif /* * Class: ProjektJNIPole * Method: posliPoleInt * Signature: ([I[I)V */ JNIEXPORT void JNICALL Java_ProjektJNIPole_posliPoleInt (JNIEnv *, jobject, jintArray, jintArray); /* * Class: ProjektJNIPole * Method: ziskejPoleInt * Signature: ()[I */ JNIEXPORT jintArray JNICALL Java_ProjektJNIPole_ziskejPoleInt (JNIEnv *, jobject); /* * Class: ProjektJNIPole * Method: posliPoleDouble * Signature: ([D)V */ JNIEXPORT void JNICALL Java_ProjektJNIPole_posliPoleDouble (JNIEnv *, jobject, jdoubleArray); /* * Class: ProjektJNIPole * Method: ziskejPoleDouble * Signature: ()[D */ JNIEXPORT jdoubleArray JNICALL Java_ProjektJNIPole_ziskejPoleDouble (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
Teraz si preberieme čo znamená opis v header file pri jednotlivých metód. napr.
/*
* Class: ProjektJNIPole
* Method: posliPoleInt
* Signature: ([I[I)V
*/
- Class: ProjektJNIPole - tu to je jasné, meno zdrojovej triedy, v ktorej sa metóda nachádza
- Method: posliPoleInt - opäť úplne jasné, jedná sa o meno metódy
- Signature: ([I [I) V - toto je najzaujímavejšia časť, špecifikuje jej vstupné parametre a návratový typ metódy. V našom konkrétnom prípade je metóda typu void a teda návratový parameter je "V" a vstupný parameter sú dve polia int "([I [I)"
/*
* Class: ProjektJNIPole
* Method: ziskejPoleDouble
* Signature: ()[D
*/
- Class: ProjektJNIPole - meno zdrojové triedy, v ktorej sa metóda nachádza
- Method: ziskejPoleDouble - jedná sa o meno metódy
- Signature: () [D - V tomto konkrétnom prípade je návratový typ poľa double "[D" a nemá žiadny vstupný parameter "()".
Java polia typy | JNI označenie poľa typov |
---|---|
boolean [] | [Z |
char [] | [C |
byte [] | [B |
short [] | [S |
int [] | [I |
long [] | [J |
float [] | [F |
double [] | [D |
void | V |
native byte [] vystupInt2(int [] pole1,double [] vektorDouble); /* Signature: ([I[D)[B */ native char [] vlozHodnotu(double [][] maticeDouble,float [][][] matice3D,long [][] maticeLong); /* Signature: ([[D[[[F[[J)[C */
Teraz si ukážeme ako vyzerá zdrojový kód samotnej zdieľané knižnice vychádzajúci zo zverejneného header súboru:
#include <jni.h> #include <stdio.h> #include "ProjektJNIPole.h" #define MAX 5 JNIEXPORT void JNICALL Java_ProjektJNIPole_posliPoleInt(JNIEnv *env, jobject obj, jintArray poleInt1, jintArray poleInt2){ // zjistime velikost poli jsize velikostPole1 = (*env)->GetArrayLength(env,poleInt1); jsize velikostPole2 = (*env)->GetArrayLength(env,poleInt2); // preneseme vstupni pole do poli jint jint *poleINT1 = (*env)->GetIntArrayElements(env,poleInt1,NULL); jint *poleINT2 = (*env)->GetIntArrayElements(env,poleInt2,NULL); int i; int poleInt [velikostPole1]; if(velikostPole1 == velikostPole2) { for(i=0;i<velikostPole1;i++) { poleInt[i] = poleINT1[i]+poleINT2[i]; } } else { printf("Pole se nerovnaji - ukonceni nativni metody"); return ; } printf("Provedeme vypis pole jenz je soucet vstupnich poli - metoda posliPoleInt \n"); for(i=0;i<velikostPole1;i++){ printf("index pole [%d] hodnota= %d\n",i,poleInt[i]); } } JNIEXPORT jintArray JNICALL Java_ProjektJNIPole_ziskejPoleInt(JNIEnv *env, jobject obj){ // z duvodu zjednoduseni pouzijeme velikost pole definici MAX jint poleI [] = {56,68,-456,216,66}; jintArray poleInt = (*env)->NewIntArray(env,MAX); (*env)->SetIntArrayRegion(env,poleInt,0,MAX,poleI); return poleInt; } JNIEXPORT void JNICALL Java_ProjektJNIPole_posliPoleDouble(JNIEnv *env, jobject obj, jdoubleArray poleDouble){ // zjistime velikost poli jsize velikostPole1 = (*env)->GetArrayLength(env,poleDouble); // preneseme vstupni pole do poli jdouble jdouble *poleDOUBLE1 = (*env)->GetDoubleArrayElements(env,poleDouble,NULL); int i; for(i=0;i<velikostPole1;i++){ printf("index pole [%d] hodnota= %f\n",i,poleDOUBLE1[i]); } } JNIEXPORT jdoubleArray JNICALL Java_ProjektJNIPole_ziskejPoleDouble(JNIEnv *env, jobject obj){ // vytvorime double pole viz. C double poleD [MAX]; poleD[0]=-34.4556; poleD[1]=79635.65; poleD[2]=123.455; poleD[3]=-985.456; poleD[4]=-22.789; // vytvorime jdouble pole viz. JNI jdouble pole [MAX]; int i; for(i=0;i<MAX;i++){ pole[i]=(jdouble)poleD[i]; } // vytvorime JNI pole jdoubleArray poleDouble = (*env)->NewDoubleArray(env,MAX); // naplnime JNI pole daty (*env)->SetDoubleArrayRegion(env,poleDouble,0,MAX,pole); return poleDouble; }
Metóda posliPoleInt: Prvá metóda nemá návratový typ. Vstupnými parametrami sú dve polia Integer. Ako prvý zistíme hodnotu veľkosti vstupujúcich polí. Potom prenesieme pole jintArray do poľa jint. S poľom jint sa bude pracovať. Ak sa veľkosti polí budú rovnať, potom sa obe polia spočítajú. Inak sa metóda ukončí. A nakoniec sa pole pre kontrolu vypíše.
Metóda ziskejPoleInt: Druhá metóda metóda má návratový typ poľa Integer. Naplním jint pole hodnotami. Ako ďalšie vytvoríme objekt jintArray a definujeme jeho veľkosť. Nakopírujeme pole s hodnotami do vzniknutého objektu jintArray. A potom dané pole nastavíme ako návratový typ.
Metóda posliPoleDouble: Tretia metóda nemá návratový typ. Vstupujúcim poľom je pole double, v JNI známu ako jdoubleArray. Zistíme veľkosť poľa, prenesieme jdoubleArray do poľa jdouble a potom vykonáme výpis daného poľa.
Metóda ziskejPoleDouble: Štvrtá metóda má návratový typ poľa double. Najskôr si vyrobíme štandardné pole double v syntaxi C. Toto pole prenesieme do JNI poľa typov jdouble. Ako ďalšie vytvoríme objekt jdoubleArray a definujeme jeho veľkosť. Nakopírujeme pole s hodnotami do vzniknutého objektu jdoubleArray. A potom dané pole nastavíme ako návratový typ.
Prevedieme nastavenie kompilátora a linker - špecifikujeme
x86_64-w64-mingw32-gcc
. Ako ďalší krok nasleduje build
knižnice.
Po zbuildování knižnice do * .dll sa prepneme späť na Java perspektívu. Presunieme zdieľanú knižnicu do iného adresára, napr. \ Src \, a vykonáme úpravu východiskovej Java triedy. Načítanie knižnice tentoraz umiestnime priamo do main metódy a nedáme do výnimky.
public class ProjektJNIPole { private static int [] poleI1 = {5,6,12,35}; private static int [] poleI2 = {1,2,3,4}; private static double [] poleD1 = {35.56,8987.554,99.785,123.567}; native void posliPoleInt(int [] poleI1,int poleI2 []); native int [] ziskejPoleInt(); native void posliPoleDouble(double [] poleD1); native double [] ziskejPoleDouble(); public static void main(String[] args) { System.out.println("Testovaci vypis"); System.loadLibrary("src/libProjektJNIPole"); ProjektJNIPole program = new ProjektJNIPole(); /** Provedem zavolani metod s datovymi typy int **/ program.posliPoleInt(poleI1, poleI2); int [] poleIntNative = program.ziskejPoleInt(); for(int c : poleIntNative) { System.out.println("Nativni pole (int)\t"+c); } /** Provedem zavolani metod s datovymi typy double **/ program.posliPoleDouble(poleD1); double [] poleDoubleNative = program.ziskejPoleDouble(); for(double c:poleDoubleNative) { System.out.println("Nativni pole (double)\t"+c); } } }
výsledok:
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkamiStiahnuté 511x (103.11 kB)