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í.

5. diel - JNI - Príklad v Eclipse bez Makefile as reťazcom

V minulom tutoriále o Java Native Interface sme si ukázali, ako vytvoriť JNI aplikáciu v IDE Eclipse CDI a použili sme k tomu Makefile.

Dnes si budeme pomáhať trochu aj príkazovým riadkom. Nie každý chce totiž v Eclipse používať Makefile. Opätovne je projekt takmer identický ako v predchádzajúcich dvoch dieloch. A aby sme to trochu okorenili, nebudeme využívať len primitívne dátové typy, ale pohráme si aj so STRING.

Osnova postupu

  1. Vytvoríme Java projekt vrátane spúšťací triedy (.java) a skompilujeme pre Java8, 7, 6, ... ( .class)
  2. Vytvoríme hlavičkový súbor (* .h) a prekonvertuje do C / C ++ projektu
  3. Z header filu (hlavičkového súboru) vytvoríme source file (zdrojový súbor * .c)
  4. Nastavíme kompilátor a linker v Eclipse CDT IDE
  5. Vykonáme kompiláciu a linkovanie danej zdieľané knižnice (* .dll)
  6. Upravíme spúšťacie Java triedu, aby sme načítali natívne knižnicu a zavoláme natívne metódy z Javy

1 - Tvorba a kompilácie Java projektu

Ako prvý krok samozrejme skontrolujeme perspektívu, musí byť nastavená Java. Ďalej vytvoríme Java projekt, ktorý si nejako pomenujeme. Vytvoríme spúšťací triedu bez balíčka a doplníme telo spúšťacie metódy + navrhneme natívne metódy. Program spustíme a dole v konzole si skontrolujeme kontrolný výstup. Je to identické z predchádzajúcej kapitolou.

public class ProgramString {
    native void metodaTest();
    native String posliString(String str);
    public static void main (String [] args) {
        System.out.println("Testovací výpis z Javy");
    }
}

Čo danej metódy vlastne robia? Prvá metóda je jasná (pozri. Minulej kapitoly). Druhá metóda má návratový typ String, čo znamená, že natívny metóda nám prenesie hodnotu typu String z natívne časti programu do interpretované časti programu a zároveň je String aj parameter interpretované časti, ktorý sa prenesie do natívne. Iba vykonáme zmenu toho reťazca. Prakticky je to triviálne časť.

Java trieda s natívnymi metódami - JNI - Java Native Interface

2 - Vytvorenie hlavičkového súboru a konverzie projektu

(Pre Java 9,8,7,6, ...) Pretože nám Eclipse neumožňuje v Project exploreru zobraziť * .class (skompilovanej Java triedy) a my potrebujeme vyrobiť cez "javah" hlavičkový súbor, tak budeme musieť spustiť navigator, ktorý nám zobrazí * .class súbory.

nastavenie navigátora - JNI - Java Native Interface

V navigátora klikneme na adresár \ bin \ a za pomocou klávesovej skratky CTRL + ALT + T sa nám v Eclipse zobrazí terminál. Jedná sa o obyčajný command prompt, dostupný v Eclipse od verzie 3.7. Vďaka nemu vygenerujeme za pomocou príkazu súbor * .h. Cez Popup menu vyvoláme refresh projektu a všimneme si vzniku súboru ProgramString.h (header file * .h) v adresári \ bin \. Tento súbor okamžite presunieme do adresára \ src \.

javah -jni ProgramString

Pre Java 10,11 [18.9], 12 [19.3], ...: V adresári \ src \ spustíme terminal a zadáme tento príkaz.

javac -h . ProgramString.java
Vytvorenie hlavičkového súboru - JNI - Java Native Interface

Ako ďalšie vykonáme konverziu z Java Projektu na C / C ++ projekt. K tomu samozrejme nestačí len zmeniť perspektívu. Konverziu vykonáme podľa obrázku. Označíme projekt, ktorý chceme skonvertovať, a vyvoláme Popup okno -> new -> other. Objaví sa dialógové okno New, vyberieme C / C ++ -> zvolíme Convert to a C / C ++ Project. Ďalej nastavíme vlastnosti projektu. Zvolíme projekt a vyberieme C Projekt, zvolíme Shared Library (zdieľaná knižnica) project a typ kompilátora v našom prípade MinGW. Postup je takmer identický ako v predchádzajúcom článku.

Zmena projektu - JNI - Java Native Interface

Môžeme si všimnúť zmien Project exploreru v projekte. Projekt sa prekonvertovať. Samozrejme automaticky došlo k zmene perspektívy na C / C ++. Po konverzii projektu nám vzniknú nejaké error, ale zatiaľ si ich nevšímajte, čoskoro sa ich zbavíme.

3 - Vytvorenie zdrojového súboru C / C ++

Teraz si do adresára \ src \, kde je umiestnený zdrojový kód Java aplikácie a hlavičkový súbor, vytvoríme zdrojový kód pre knižnicu "ProgramString.c". Označíme daný adresár a opäť vyvoláme Popup okno. Vyberieme cestu New -> File -> a objaví sa nám opäť dialógové okno. Zvolíme adresár, kam sa má vytvoriť, a do File name vyplníme názov.

Vytvorenie zdrojového súboru C / C ++ - JNI - Java Native Interface

Akonáhle vytvoríme zdrojový súbor * .ca vložíme tento kód, ktorý uložíme, tak by mali samy zmiznúť spomínané error. Doplníme hlavičky metód (funkcií) deklaráciami a vyplníme tela daných funkcií.

#include <jni.h>
#include <stdio.h>
#include "ProgramString.h"
#include "string.h"
JNIEXPORT void JNICALL Java_ProgramString_metodaTest(JNIEnv *env, jobject obj){
    printf("Testovaci Vypis z Nativni casti JNI Programu");
}

JNIEXPORT jstring JNICALL Java_ProgramString_posliString(JNIEnv *env, jobject obj, jstring str){
    // zpracujeme vstupni retezec
    const char *retezec = (*env)->GetStringUTFChars(env, str, 0);
    printf("Zde je vlozeny retezec : %s\n", retezec);
    //  POZOR pouze 256 znaku
    char veta [256];
    //  vlozeni retezce do pole charu
    strcpy(veta,"Ahoj jak se mas ?");
    // slouceni retezcu v C-cku
    strcat(veta,retezec);
    jstring vystup = (*env)->NewStringUTF(env,veta);
    return vystup;
}

Teraz si trochu preberieme čo sme vykonali. Prvý funkciu kvôli jednoduchosti preskočíme. Druhá funkcia už zaujímavejšie. C-čko samotnej nepodporuje String, takže je nutné ho za pomoci JNI metódy (funkcia) "GetStringUTFChars ()" previesť na pole char. Tu je zoznam všetkých JNI fukcií podporovaných v JNI API. Syntax C nebudem rozoberať. Ďalšie funkcie "NewStringUTF ()" vytvára String, ktorý potom presunieme do interpretované časti, je to návratová hodnota našej funkcie.

Vypísanie zdrojového kódu - JNI - Java Native Interface

4 - Nastavenie kompilátora a linker

Teraz nás čaká najnudnejší, ale aj najdôležitejšia časť. Prevedieme nastavenie kompilátora / linker v Eclipse IDE. Klikneme (označíme) projekt a stlačíme ALT + ENTER. V strome si vyberieme C / C ++ Build -> Settings -> a tu v Configuration nastavíme All configurations.

nastavenie projektu - JNI - Java Native Interface

Teraz vykonáme nastavenie kompilátora. V strome v záložke Tool Settings vyberieme možnosť GCC C Compiler a do Command vložíme kompilátor pre 64bit x86_64-w64-mingw32-gcc. Skontrolujeme parametre v All options -O3 -Wall -c -fmessage-length=0. Pravdepodobne v defaultu budete mať - O0, takže sa presuňte do Optimization a nastavte -O3. Inak ak by sme nezastavili PATH k jni.ha jni_md.h, do PATH by sme tu kompilátora museli v možnosti Includes (-I) danej paths nastaviť.

nastavenie kompilácie - JNI - Java Native Interface

Ďalej vykonáme nastavenie linker. V strome sa prepneme na MinGW Linker a do Command opäť vložíme kompilátor pre 64bit x86_64-w64-mingw32-gcc. Do možnosti Miscellaneous doplníme do Linker flags tento reťazec -Wl,--add-stdcall-alias a potom sa späť prepneme do MinGW C Linker. Tu uvidíme upravený All options. (-Shared ... je tam defaultne a označuje tvorbu * .dll).

nastavenie linker - JNI - Java Native Interface

Zvolíme Apply a OK. Tým máme nastavený kompilátor aj builder.

5 - Kompilácia do * .dll

Čaká nás teda prevedenie tzv. "Buildu". Najskôr však vykonáme vyčistenie projektu. V menu zvolíme možnosť Project -> Clean ... -> označíme projekt a vypneme automatický build.

Potom klikneme na známe kladivko a build sa vykoná. Zdieľaná knižnica vznikne v adresári Debug, odkiaľ ju budeme v Java aplikácii načítať.

prevedenie buildu - JNI - Java Native Interface

6 - Úprava Java triedy a volanie natívne metódy

Po úspešnom zbuildování * .dll knižnice sa vrátime do Javy. Prepneme perspektívu a zobrazíme si zdrojový kód spúšťací triedy v Jave. Najskôr vykoná načítanie knižnice a potom zavoláme natívne metódy.

public class ProgramString {
    static {
        try {
            System.loadLibrary("libProjektJNIEclipse");
            System.out.println("Nactena knihovna                                libProjektJNIEclipse.dll");
        }
        catch(UnsatisfiedLinkError e){
            System.err.println("Nelze nacist knihovnu                           libProjektJNIEclipse.dll");
            System.err.println(e.getMessage());
        }
    }
    native void metodaTest();
    native String posliString(String str);
    public static void main(String[] args) {
        System.out.println("Testovaci vypis z JAVY ");
        ProgramString program = new ProgramString();
        program.metodaTest();
        String s = "Isaac Asimov";
        System.out.println("Zde je vystup : " +program.posliString(s));
    }
}


Nastavenie Java triedy pre volanie native metód - JNI - Java Native Interface

Pred samotným spustením Java triedy je v IDE nutné opäť projekt vyčistiť. (Project -> Clean). Opätovne je nutné JVM informovať, kde danú * .dll hľadať a toho docielime nastavením v konfigurátore spustení. Hore v menu zvolíme Run -> Run configurations ... a prevedieme nastavenie. V strome si nájdeme spúšťací triedu prepneme záložku Arguments -> VM argument, kam vložíme -Djava.library.path=Debug. Potom klikneme na Apply a Run a uvidíme výsledok.

Spustenie JNI projektu - JNI - Java Native Interface

Využívať v kóde * .dll umiestnenou v adresári Debug nie je moc chytré. Každým spúšťaním prebieha kompilácie a štruktúra adresára Debug sa pokazí a prestane fungovať. Preto odporúčam vytvoriť nový adresár, napr. "Dll", a do neho knižnicu nakopírovať. Pri spustení cez IDE je vhodné upraviť VM argument -Djava.library.path=dll. Všetko by malo bežať v poriadku. Ak aplikáciu spúšťame z príkazového riadku cez IDE v konzolu alebo priamo cez command prompt, nesmieme zabudnúť, že keď spustím z adresára \ bin \, v tomto adresári sa adresár \ dll \ nenachádza a preto je nutné povedať JVM nech hľadá adresár \ dll \ o úroveň vyššie, priamo v roote projektu.

testovacie výpis - JNI - Java Native Interface

To je pre zatiaľ všetko, základná kostra riešenia bola ukázaná a jemné detaily rôznych dátových typov, objektov, pointer vs. referencie, vlákien, apod., to už bude na vás.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 9x (74 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
JNI - Príklad v Eclipse s Makefile
Všetky články v sekcii
JNI - Java Native Interface
Preskočiť článok
(neodporúčame)
JNI - Príklad v Eclipse s C ++
Článok pre vás napísal Robert Michalovič
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
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