3. díl - JNI - První příklad Java Native Interface bez IDE

Java Pro pokročilé JNI JNI - První příklad Java Native Interface bez IDE

V minulém tutoriálu o JNI jsme si vytvořili program Hello world několika způsoby pro C, C++ a Javu. Dnes vytvoříme první JNI aplikaci. Nevyužijeme zatím žádné IDE a vše vytvoříme pouze přes příkazový řádek. Možná zjistíte, že přes CMD vám to bude připadat jednodušší a snazší, než v dalších dílech přes IDE. Tento díl má prakticky objasnit pouze princip řešení. Zde navrhnu postup, který je nutno splnit krok za krokem. Vypadá to sice složitě, ale zas takový horor to není. V příštích dílech, kdy budeme využívat IDE, zjistíte, že některé kroky s IDE jsou složitější. Díky IDE ovšem máte mnohem větší přehled v projektu a vytvářet rozsáhlejší nativní knihovny bez IDE je prakticky projev šílenství.

Postup

Budeme postupovat podle této osnovy:

  1. Vytvoříme Java projekt včetně spouštěcí třídy (*.java)
  2. Tuto třídu zkompilujeme, získáme (*.class)
  3. Z kompilované třídy vytvoříme header file (hlavičkový soubor) pro C/C++ (*.h)
  4. Z header filu (hlavičkového souboru) vytvoříme source file (zdrojový soubor *.c)
  5. Daný zdrojový soubor zkompilujeme a nalinkujeme, vznikne *.dll soubor
  6. Upravíme spouštěcí Java třídu, abychom načetli nativní knihovnu
  7. Zavoláme nativní metody z Javy

1 - Tvorba projektu a Java třídy

Jako první samozřejmě spustíme příkazový řádek (command prompt). Vytvoříme adresář

md ProgramJNI

a přesuneme se do něj

cd ProgramJNI

Dále vytvoříme soubor

fsutil file createnew programJava.java 0

jenž bude sloužit k uložení zdrojového kódu v Javě. Dále si přes Notepad otevřeme soubor

notepad ProgramJava.java

a vložíme (napíšeme) kód, který je nutný pro úspěšnou kompilaci a spuštění programu. Soubor uložíme a Notepad ukončíme.

public class ProgramJavaJNI {
        native void volameMetodu();
        native void posliInt(int cislo);
        public static void main (String [] args) {
                System.out.println("Testovací Vypis Java");
        }
}
Vytvoříme Java třídu

Nyní si trochu proberme co jsme vlastně napsali:

  • Upozorňuji, že třída není umístěna v balíčku, s využitím balíčku je řešení trochu komplikovanější a není to předmětem tohoto dílu. Můžete si to sami v rámci vlastní iniciativy vyzkoušet, ale upozorňuji, že vám to asi napoprvé nepoběží.
  • Zde nejspíše poprvé vidíte praktické využití rezervovaného slovíčka "native". Ano, tady to je, to je přesně to správné použití. Jedná o specifikaci metod pro JNI. Jakákoliv metoda označená "native" říká při volání JVM kde ji má hledat.
  • Název nativních metod pro MinGW je nutno pojmenovat vždy s malým písmenkem. Kompilace/linkování vám proběhne, ale JVM vám při zavolání vyvolá exception. Tak to tedy v Java SE7 ještě fungovalo.
  • Co dané metody vlastně dělají? První metoda nemá návratový typ. Druhá metoda je opět void, ale do nativní části kódu posíláme číselnou hodnotu. Jedná o celé číslo typu integer. Prakticky provedeme za pomocí JNI pouze výpis do konzole, nic složitějšího pro začátek není nutné.

2 - Kompilace Java třídy

Provedeme zkompilování programu a poté jeho testovací spuštění. Protože jsme nastavili Javu do systémových proměnných jako PATH, je nám umožněno volat jakýkoliv příkaz v jakémkoliv adresáři. Za pomocí příkazu

javac ProgramJavaJNI.java

provedeme kompilaci. Vysledkem bude soubor ProgramJavaJNI­.class. Tento soubor lze spustit příkazem

java ProgramJavaJNI
Zkompilujeme Java program

3 - Tvorba hlavičkového souboru C/C++

Nyní vygenerujeme header file ( hlavičkový soubor *.h ), který využijeme pro zdrojový soubor. To provedeme příkazem "javah -jni ProgramJavaJNI". Toto nám vygeneruje soubor ProgramJavaJNI.h který si za pomocí příkazu můžeme prohlédnout. Abychom to nemusely přepisovat otevřeme si jej v notepadu ale NESMÍTE jej editovat a ukládat do něj. Nějaký podrobnější popis daného hlavičkového souboru bude až v příštích kapitolách.

Tvorba hlavičkového souboru

4 - Tvorba zdrojového souboru C/C++

Nyní si vytvoříme nový soubor "ProgramJavaJNI.c", který bude sloužit jako zdrojový soubor. To opět docílíme příkazem ( "fsutil file createnew ProgramJava.c 0" ) a tento soubor opětovně otevřeme v notepadu.
Těla metod z hlavičkového souboru zkopírujeme a doplníme vnitřek metod ( funkcí ). Jak jsem výše vzpomenul, bude se jednat pouze o výpisové funkce, takže v C voláme pouze funkci "printf". Nic složitejšího v tomto článku řešit nebudeme. První metoda neprovádí nic složitého pouze výpis a trivialní součet a výpis daneho součtu.

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

JNIEXPORT void JNICALL Java_ProgramJavaJNI_volameMetodu(JNIEnv *env, jobject obj){
        printf("Zde je vystup pro zavolanou nativni metodou\n");
        int a=10;
        int b=25;
        int c=a+b;
        printf("Soucet je : %d \n",c);
}

JNIEXPORT void JNICALL Java_ProgramJavaJNI_posliInt(JNIEnv *env, jobject obj, jint cislo){
        printf("Zde je vystup pro zavolanou nativni metodou : %d \n",cislo);
}

Dále je nutno doplnit identifikátory parametrů do parametrů metod(funkci). Taktéž nyní nebudeme rozebírat includované soubory.

Vytvoření zdrojového souboru

5 - Kompilace C/C++ souboru

Zde přichází trochu komplikovanější část. Počítám že jste dle kap.1 nakopírovaly jni.h a jni_md.h do definovaného adresáře. Pokud ano příkaz bude výrazně jednodušší. Jako první postup předvedu kompilaci a build s nakopírovanými hlavičkovými soubory od JNI. Pokud používáte kompilátor podporující 32bit/64bit neměl by vzniknout naprosto žádný problém. Problém by mohl vzniknout pokud máte pouze 32bit kompilátor a snažíte se provést build na 64bit OS. Buildování by se provedlo ale JVM v 7 kroku by vám vyhodil vyjímku o problémech načtění 32bit knihovny v 64bit JVM.

Zadame tento příkaz ke kompilaci : "x86_64-w64-mingw32-gcc -c ProgramJavaJNI.c -o ProgramJavaJNI.o"
a vytvoříme ProgramJavaJNI.o Pak zadáme tento příkaz pro linkování : "x86_64-w64-mingw32-gcc -Wl,--add-stdcall-alias -shared -o knihovna.dll ProgramJavaJNI.o"
a vytvoříme soubor knihovna.dll

Pokud bychom neprovedly nakopírování jni.h a jni_md.h do definovaných adresářů dle kapitoly 1 příkaz pro kompilaci by vypadal takto. Samozřejmě cestu k adresářům v Javě si upravte podle vlastní instalace. "x86_64-w64-mingw32-gcc -I"C:\Program Files\JavaJDK\in­clude" -I"C:\Program Files\JavaJDK\in­clude\win32" -c ProgramJavaJNI.c -o ProgramJavaJNI.o"

Buildujeme Zdroják

6 - Úprava Java třídy

Opětovně se vrátíme do zdrojového kódu Java souboru. Zde provedeme úpravy. První zásadní úprava bude načtení knihovny a druhá vyvolání jejich nativních metod. Prakticky zde není co pokazit. Soubor zdrojového kódu samozřejmě poté uložíme.

public class ProgramJavaJNI {
        static {
                try {
                        System.loadLibrary("knihovna");
                        System.out.println("Nactena knihovna knihovna.dll");
                }
                catch(UnsatisfiedLinkError e){
                        System.err.println("Nelze nacist knihovnu knihovna.dll");
                        System.err.println(e.getMessage());
                }
        }
        native void volameMetodu();
        native void posliInt(int cislo);
        public static void main (String [] args) {
                System.out.println("Testovací Vypis Java");
                ProgramJavaJNI program = new ProgramJavaJNI();
                program.volameMetodu();
                program.posliInt(99);
        }
}

Načtení knihovny provádím ve statickém bloku, tím docílím toho, že se načte jako naprosto první při vzniku objektu, tedy ještě před vznikem konstruktoru. Protože vše je umístěné v jednom adresáři a Java třída je bez balíčku, JVM všechno snadno načte a spustí bez dodatečných parametrů.

Úprava Java třídy

7 - Volání nativních metod z Javy

Konečně přichází finále, kdy si vyzkoušíme první program využívající JNI. Samozřejmě je nutno třídu nejdříve zkompilovat známým příkazem "javac" a poté program spustíme příkazem "java".

Připomínám, že *.dll knihovny jako produkt nativního jazyka zdědily slabiny nativních jazyků a to je např. nekompatibilita mezi různými operačními systémy a také i mezi různými procesory. Tak abyste nebyli nemile překvapeni. Výše uvedený příklad, jenž je přílohou, je knihovna pro 64bit Windows, zbuildovaná pod procesorem Intel. Na 32bit Windows nefunguje.

TestCMD

 

Stáhnout

Staženo 4x (15.89 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

  Aktivity (5)

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

Jak se ti líbí článek?
Celkem (1 hlasů) :
55555


 


Miniatura
Všechny články v sekci
JNI - Java Native Interface
Miniatura
Následující článek
JNI - Příklad v Eclipse s makefile

 

 

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