7. díl - JNI - Primitivní datové typy

Java Pro pokročilé JNI JNI - Primitivní datové typy

V minulém tutoriálu o Java Native Interface jsme si vyzkoušeli pokročilejší příklad s řetězci a C++. V dnešním dílu se budeme věnovat primitivním datovým typům.

Primitivní datové typy

V předchozích dílech jsme si ukázali funkční postupy vytvářející *.dll. Nyní si vyberte, který vám vyhovuje, a vyzkoušejte si různé primitivní datové typy, které tu budou zveřejněny. Není to nijak složité, když existuje vzorový příklad. Zde je seznam všech primitivních datových typů dostupných jak v Javě, Cčku, tak i v nativní části (JNI).

JAVA typy JNI typy C typy JNI Velikost(bit)
boolean jboolean neobsahuje 8 (unsigned)
byte jbyte neobsahuje 8
char jchar char 16 (unsigned)
short jshort short 16
int jint int 32
long jlong long 64
float jfloat float 32
double jdouble double 64
void void void 0
true JNI_TRUE 1 -
false JNI_FALSE 0 -

Popis metod je docela jednoduchý.

public class DatoveTypyPrimitivni {
    static {
        //... načteme dll
    }
    private native void vypisBoolean(boolean hodnota);
    private native boolean ziskejBoolean();
    private native void vypisByte(byte hodnota);
    private native byte ziskejByte();
    private native void vypisZnak(char znak);
    private native char ziskejZnak();
    private native void nastavShort(short hodnota);
    private native short ziskejShort();
    private native void nastavInt(int hodnota);
    private native int ziskejInt();
    private native void nastavLont(long hodnota);
    private native long ziskejLong();
    private native void nastavFloat(float hodnota);
    private native float ziskejFloat();
    private native void nastavDouble(double hodnota);
    private native double ziskejDouble();
    // Konzolovy vypis JNI metod probehne az na konci celeho naseho programu
    public static void main(String args []){
        System.out.println("Start Programu");
        DatoveTypyPrimitivni program = new DatoveTypyPrimitivni();
        program.vypisBoolean(false);
        System.out.println("Zde je hodnota z JNI : "+program.ziskejBoolean());
        program.vypisByte((byte)77);
        System.out.println("Ziskej hodnotu z Byte z JNI : "+program.ziskejByte());
        program.vypisZnak('Z');
        System.out.println("Ziskej Znak z JNI : "+program.ziskejZnak());
        short hodnota = 14563;
        program.nastavShort(hodnota);
        System.out.println("Ziskej short z JNI : "+program.ziskejShort());
        program.nastavInt(12312345);
        System.out.println("Ziskej int z JNI : "+program.ziskejInt());
        long hodnotaLong = (long)674843456;
        program.nastavLont(hodnotaLong);
        System.out.println("Ziskej long z JNI : "+program.ziskejLong());
        float hodnotaFloat = (float) 4565.35967;
        program.nastavFloat(hodnotaFloat);
        System.out.println("Ziskej float z JNI : "+program.ziskejFloat());
        double hodnotaDouble = (double)45456465.45994;
        program.nastavDouble(hodnotaDouble);
        System.out.println("Ziskej double z JNI : "+program.ziskejDouble());
        System.out.println("Konec Programu");
    }
}

Zde je vygenerovaný header file. Pojmenovaný "primitivni.h".

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

#ifndef _Included_DatoveTypyPrimitivni
#define _Included_DatoveTypyPrimitivni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     DatoveTypyPrimitivni
 * Method:    vypisBoolean
 * Signature: (Z)V
 */
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_vypisBoolean
  (JNIEnv *, jobject, jboolean);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    ziskejBoolean
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_DatoveTypyPrimitivni_ziskejBoolean
  (JNIEnv *, jobject);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    vypisByte
 * Signature: (B)V
 */
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_vypisByte
  (JNIEnv *, jobject, jbyte);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    ziskejByte
 * Signature: ()B
 */
JNIEXPORT jbyte JNICALL Java_DatoveTypyPrimitivni_ziskejByte
  (JNIEnv *, jobject);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    vypisZnak
 * Signature: (C)V
 */
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_vypisZnak
  (JNIEnv *, jobject, jchar);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    ziskejZnak
 * Signature: ()C
 */
JNIEXPORT jchar JNICALL Java_DatoveTypyPrimitivni_ziskejZnak
  (JNIEnv *, jobject);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    nastavShort
 * Signature: (S)V
 */
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavShort
  (JNIEnv *, jobject, jshort);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    ziskejShort
 * Signature: ()S
 */
JNIEXPORT jshort JNICALL Java_DatoveTypyPrimitivni_ziskejShort
  (JNIEnv *, jobject);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    nastavInt
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavInt
  (JNIEnv *, jobject, jint);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    ziskejInt
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_DatoveTypyPrimitivni_ziskejInt
  (JNIEnv *, jobject);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    nastavLont
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavLont
  (JNIEnv *, jobject, jlong);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    ziskejLong
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_DatoveTypyPrimitivni_ziskejLong
  (JNIEnv *, jobject);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    nastavFloat
 * Signature: (F)V
 */
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavFloat
  (JNIEnv *, jobject, jfloat);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    ziskejFloat
 * Signature: ()F
 */
JNIEXPORT jfloat JNICALL Java_DatoveTypyPrimitivni_ziskejFloat
  (JNIEnv *, jobject);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    nastavDouble
 * Signature: (D)V
 */
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavDouble
  (JNIEnv *, jobject, jdouble);

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    ziskejDouble
 * Signature: ()D
 */
JNIEXPORT jdouble JNICALL Java_DatoveTypyPrimitivni_ziskejDouble
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Nyní si konečně probereme co znamená popis v header file u jednotlivých metod. Např.:

/*
 * Class:     DatoveTypyPrimitivni
 * Method:    vypisBoolean
 * Signature: (Z)V
 */
  • Class: DatoveTypyPri­mitivni - Zde je to jasné, jméno zdrojové třídy, ve které se metoda nachází
  • Method: vypisBoolean - opět naprosto jasné, jedná se o jméno metody
  • Signature: (Z)V - toto je nejzajímavější část, specifikuje její vstupní parametry a návratový typ metody. V našem konkrétním případě je metoda typu void a tudíž návratový parametr je "V" a vstupní parametr je boolean "(Z)"
/*
 * Class:     DatoveTypyPrimitivni
 * Method:    ziskejFloat
 * Signature: ()F
 */
  • Class: DatoveTypyPri­mitivni - jméno zdrojové třídy, ve které se metoda nachází
  • Method: ziskejFloat - jedná se o jméno metody
  • Signature: ()F - V tomto konkrétním případě je návratový typ typu Float "F" a nemá žádný vstupní parametr "()"
Java typy Označení typu
boolean Z
char C
byte B
short S
int I
long J
float F
double D
void V

Je pochopitelné, že toto je jen základní popis v případě jednoho parametru. V případě metod s více parametry s primitivními datovými typy je řešením jejich kombinace. Sami vidíte, že návrh od programátorů JNI je velmi logický.

native int vystupInt2(int hodnota2,int hodnota3);  /* Signature: (II)I */
native void vlozHodnotu(double cisDouble,float cisFloat,int cisInt);  /* Signature: (DFI)V */

Nyní si ukážeme jak vypadá zdrojový kód samotné sdílené knihovny vycházející ze zveřejněného header souboru.

#include <jni.h>
#include <stdio.h>
#include "primitivni.h"

JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_vypisBoolean(JNIEnv *env, jobject obj, jboolean bool){
    printf("Zde je vypsan dany boolean : %d \n",bool);
    jboolean boolea = JNI_TRUE;
    printf("Zde je vypsan dany boolean : %d \n",boolea);
}

JNIEXPORT jboolean JNICALL Java_DatoveTypyPrimitivni_ziskejBoolean(JNIEnv *env, jobject obj){
    jboolean boolea = JNI_FALSE;
    return boolea;
}
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_vypisByte(JNIEnv *env, jobject obj, jbyte bajt){
    printf("Zde je vypsan dany byte : %d \n",bajt);
    jbyte hodnota = 55;
    printf("Zde je vypsan dany byte : %d \n",hodnota);
}

JNIEXPORT jbyte JNICALL Java_DatoveTypyPrimitivni_ziskejByte(JNIEnv *env, jobject obj){
    jbyte hodnota = 22;
    return hodnota;
}
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_vypisZnak(JNIEnv *env, jobject obj, jchar znak){
    printf("Zde je vypsan dany znak : %c \n",znak);
    char zna ='C';
    jchar znakk ='D';
    printf("Zde je vypsan dany znak : %c \n",zna);
    printf("Zde je vypsan dany znak : %c \n",znakk);
}

JNIEXPORT jchar JNICALL Java_DatoveTypyPrimitivni_ziskejZnak(JNIEnv *env, jobject obj){
    char znakC ='X';
    jchar znakJ = znakC;
    return znakJ;
}

JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavShort(JNIEnv *env, jobject obj, jshort shortik){
    printf("Zde je vypsan dany Short : %d \n",shortik);
    short cislo = 4561;
    printf("Zde je vypsan dany Short : %d \n",cislo);
}

JNIEXPORT jshort JNICALL Java_DatoveTypyPrimitivni_ziskejShort(JNIEnv *env, jobject obj){
    unsigned short cislo = 56451;
    printf("Zde je vypsan mezi Short : %d \n",cislo);
    jshort ziskejShort = cislo;
    printf("Zde je vypsan mezi Short : %d \n",ziskejShort);
    return ziskejShort;
}

JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavInt(JNIEnv *env, jobject obj, jint integer){
    printf("Zde je vypsan dany Integer : %d \n",integer);
}

JNIEXPORT jint JNICALL Java_DatoveTypyPrimitivni_ziskejInt(JNIEnv *env, jobject obj){
    jint hodnota = 45678;
    return hodnota;
}

JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavLont(JNIEnv *env, jobject obj, jlong longer){
    printf("Zde je vypsan dany Long : %d \n",longer);
    long hodnota1 = 456123;
    long hodnota2 = 7844456;
    printf("Vypsan vysledek : %d \n",(hodnota1+hodnota2));
}

JNIEXPORT jlong JNICALL Java_DatoveTypyPrimitivni_ziskejLong(JNIEnv *env, jobject obj){
    jlong cisloLong = 456785156;
    return cisloLong;
}

JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavFloat(JNIEnv *env, jobject obj, jfloat flot){
    printf("Zde je vypsan dany float : %d \n",flot);
    float cislo1 = 784.657;
    float cislo2 = 46.789;
    printf("Vypsan vysledek : %d \n",(cislo1/cislo2));
}

JNIEXPORT jfloat JNICALL Java_DatoveTypyPrimitivni_ziskejFloat(JNIEnv *env, jobject obj){
    jfloat back = 76546.8876;
    return back;
}

JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavDouble(JNIEnv *env, jobject obj, jdouble doub){
    printf("Zde je vypsan dany double : %d \n",doub);
    double hodno1 = 46657.657;
    double hodno2 = 466333.654;
    printf("Vypsan vysledek : %d \n",(hodno1+hodno2));
}

JNIEXPORT jdouble JNICALL Java_DatoveTypyPrimitivni_ziskejDouble(JNIEnv *env, jobject obj){
    jdouble cisloDouble =45667.358;
    return cisloDouble;
}

Konečně si probereme vstupní parametry JNI metod:

/* Vychozi nativni metoda v interpretované části */
private native void nastavDouble(double hodnota);
/* Hlavičkový soubor(Header File) - Signature: (D)V */
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavDouble(JNIEnv *, jobject, jdouble)
/* Zdrojový soubor (Source File)*/
JNIEXPORT void JNICALL Java_DatoveTypyPrimitivni_nastavDouble(JNIEnv *env, jobject obj, jdouble doub)
  • JNIEnv *env - Jedná se o parametr(odkaz) pro rozhraní JNI, které obsahuje metody jenž jsou nám přes daný parametr zpřístupněny
  • jobject obj - trochu problematické, ale nejbližší definice je, že se jedná o objekt, který metodu volá. Umožňuje nám pracovat v JNI s objektem, jenž se nachází a byl vytvořen v interpretované části programu
  • jdouble doub - standardní parametry metody, zde konkrétně typu double

 

  Aktivity (5)

Článek pro vás napsal Robert Michalovič
Avatar
viz. linkedin

Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!


 


Miniatura
Předchozí článek
JNI - Příklad v Eclipse s C++
Miniatura
Všechny články v sekci
JNI - Java Native Interface

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!