Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 7 - JNI - Primitivní datové typy

V minulém tutoriálu o Java Native Interface, JNI - Příklad v Eclipse s C++, 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

V příští lekci, JNI - Pole primitivních datových typů, si vyzkoušíme práci s poli různých typů.


 

Předchozí článek
JNI - Příklad v Eclipse s C++
Všechny články v sekci
JNI - Java Native Interface
Přeskočit článek
(nedoporučujeme)
JNI - Pole primitivních datových typů
Článek pro vás napsal Robert Michalovič
Avatar
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Programuji převážně v Javě SE,EE a trochu nativním C a CUDA. více viz.https://cz.linkedin.com/in/robert-michalovic
Aktivity