abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
včera 21:33 | Nová verze

Byla vydána nová major verze 1.8.0 open source systému pro filtrování nevyžádané pošty Rspamd (GitHub, ChangeLog). Z novinek lze zmínit nový framework selectors, optimalizaci modulu ClickHouse nebo vylepšení webového rozhraní.

Ladislav Hagara | Komentářů: 1
včera 18:44 | Bezpečnostní upozornění

Sabri Haddouche vytvořil stránku Browser Reaper, na které demonstruje zranitelnosti současných verzí webových prohlížečů Chrome, Safari i Firefox. Zveřejněné skripty dokážou zahltit nejen webové prohlížeče, ale v závislosti na nastavení, také celé operační systémy.

Ladislav Hagara | Komentářů: 9
23.9. 19:22 | Nová verze

Byla vydána verze 11.3 open source alternativy GitHubu, tj. softwarového nástroje s webovým rozhraním umožňujícího spolupráci na zdrojových kódech, GitLab (Wikipedie). Představení nových vlastností i s náhledy v příspěvku na blogu.

Ladislav Hagara | Komentářů: 0
22.9. 13:00 | Komunita

Do 30. října se lze přihlásit do dalšího kola programu Outreachy (Wikipedie), jehož cílem je přitáhnout do světa svobodného a otevřeného softwaru lidi ze skupin, jež jsou ve světě svobodného a otevřeného softwaru málo zastoupeny. Za 3 měsíce práce, od 4. prosince 2018 do 4. března 2019, v participujících organizacích lze vydělat 5 500 USD.

Ladislav Hagara | Komentářů: 101
21.9. 22:22 | Komunita

Společnost Purism představila kryptografický token Librem Key. Koupit jej lze za 59 dolarů. Token byl vyvinut ve spolupráci se společností Nitrokey a poskytuje jak OpenPGP čipovou kartu, tak zabezpečení bootování notebooků Librem a také dalších notebooků s open source firmwarem Heads.

Ladislav Hagara | Komentářů: 9
21.9. 20:33 | Nová verze

Společnost NVIDIA oficiálně vydala verzi 10.0 toolkitu CUDA (Wikipedie) umožňujícího vývoj aplikací běžících na jejich grafických kartách. Přehled novinek v poznámkách k vydání.

Ladislav Hagara | Komentářů: 0
21.9. 20:00 | Upozornění

Příspěvek Jak přežít plánovanou údržbu DNS na blogu zaměstnanců CZ.NIC upozorňuje na historicky poprvé podepsání DNS root zóny novým klíčem dne 11. října 2018 v 18:00. Software, který nebude po tomto okamžiku obsahovat nový DNSSEC root klíč, nebude schopen resolvovat žádná data. Druhým důležitým datem je 1. února 2019, kdy významní výrobci DNS softwaru, také historicky poprvé, přestanou podporovat servery, které porušují DNS standard

… více »
Ladislav Hagara | Komentářů: 11
21.9. 15:55 | Pozvánky

Spolek OpenAlt zve příznivce otevřených řešení a přístupu na 156. brněnský sraz, který proběhne v pátek 21. září od 18:00 v restauraci Na Purkyňce na adrese Purkyňova 80.

Ladislav Hagara | Komentářů: 0
21.9. 13:22 | Nová verze

Alan Griffiths z Canonicalu oznámil vydání verze 1.0.0 display serveru Mir (GitHub, Wikipedie). Mir byl představen v březnu 2013 jako náhrada X serveru a alternativa k Waylandu. Dnes Mir běží nad Waylandem a cílen je na internet věcí (IoT).

Ladislav Hagara | Komentářů: 0
20.9. 22:00 | Nasazení Linuxu
Stabilní aktualizace Chrome OS 69 (resp. Chromium OS), konkrétně 69.0.3497.95, přináší mj. podporu linuxových aplikací. Implementována je pomocí virtualizace, a proto je tato funkce také omezena na zařízení s dostatkem paměti a podporou hardwarové akcelerace, tudíž nejsou podporovány chromebooky s 32bitovými architekturami ARM, či Intel Bay Trail (tzn. bez Intel VT-x).
Fluttershy, yay! | Komentářů: 6
Na optické médium (CD, DVD, BD aj.) jsem naposledy vypaloval(a) data před méně než
 (14%)
 (14%)
 (20%)
 (23%)
 (24%)
 (4%)
 (0%)
Celkem 409 hlasů
 Komentářů: 35, poslední dnes 09:16
Rozcestník

Java Native Interface – voláme Javu z nativního kódu a ještě více

14. 3. 2012 | Luboš Doležel | Programování | 3695×

V našem seriálu nám doposud scházela jedna důležitá věc. Naučili jsme se, jak může Java volat nativní kód. Teď je ale na čase jí to oplatit a zavolat nazpět. Dále se podíváme na přistupování ke členským proměnným a na práci s poli.

Obsah

Hello world!

link

Spousta seriálů a návodů začíná ukázkou „Hello world“. Tento článek sice není prvním dílem, ale přesto jej také zahájíme Hello world, byť dosti neobvyklým. Následující kód je sice jako škrábat se levou rukou na pravém uchu, ale jako ukázka možností poslouží.

void helloWorld(JNIEnv* env)
{
	jclass clsSystem = env->FindClass("java/lang/System");
	jfieldID fOut = env->GetStaticFieldID(clsSystem, "out", "Ljava/io/PrintStream;");
	jobject out = env->GetStaticObjectField(clsSystem, fOut);
	jmethodID mPrintln = env->GetMethodID(env->GetObjectClass(out), "println", "(Ljava/lang/String;)V");

	env->CallVoidMethod(out, mPrintln, "Hello world!");
}

Po chvilce zděšení[*] jste asi všichni dospěli ke správému úsudku, že tento kód odpovídá jednoduchému volání System.out.println("Hello world"), akorát za použití reflexe v JNI. Jen pro zajímavost si ukážeme, jak toto volání vypadá v bajtkódu Javy:

Ale vždyť je to přece krásné! Proč jenom ještě někdo nenapsal převodník Javy do C/JNI? ;-)
   0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #3; //String Hello world
   5:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V

Získáváme ID metody a členských proměnných

link

Aby nebylo nutné opakovaně vyhledávat metody a pole (členské proměnné) podle jejich názvů a signatury, existují v JNI typy jmethodID a jfieldID, které danou metodu nebo proměnnou popisují. V případě těchto typů se nemusíme starat o uvolňování paměti. Při vytváření signatur (popisu typů) se řídíme tabulkou, která je k vidění v druhém díle seriálu, u metod pak ještě odkáži na odstavec o signaturách metod v jiném z minulých dílů.

Abychom si to shrnuli, tak signatury se mezi proměnnými a metodami liší následovně:

signatura pole
identifikátor typu
signatura metody
(identifikátory typu)typ návratové hodnoty

Další důležitou věcí je vědět, zda pole nebo metoda je, nebo není, statická. Podívejme se tedy na funkce pro získávání identifikátorů polí:

  • jfieldID GetStaticFieldID(jclass clazz, const char *name, const char *sig)
  • jfieldID GetFieldID(jclass clazz, const char *name, const char *sig)

Jedinou praktickou odlišností je tedy název funkce, toť vše. U metod to není jiné:

  • jmethodID GetMethodID(jclass clazz, const char *name, const char *sig)
  • jmethodID GetStaticMethodID(jclass clazz, const char *name, const char *sig)

Získáváme a nastavujeme hodnoty členských proměnných

link

Při získávání a nastavování hodnot opět rozlišujeme mezi statickými a nestatickými členy. Pro každý z těchto druhů existuje skupina devíti funkcí, které se odlišují datovým typem pole. Ten tedy zohledňujeme nejen v signatuře, ale při nastavování/získávání hodnoty i v názvu volané funkce. Obecná podoba funkcí je následující:

  • void SetTypField(jobject obj, jfieldID fieldID, T value)
  • void SetTypField(jobject obj, jfieldID fieldID, T value)
  • void SetStaticTypField(jclass clazz, jfieldID fieldID, T value)
  • void SetStaticTypField(jclass clazz, jfieldID fieldID, T value)

Součást názvu Typ může nabývat hodnot Boolean, Byte, Char, Short, Int, Long, Float, Double – dosti tedy kopíruje názvy boxovaných typů. Typ T už je intuitivní, nicméně přehled najdete v druhém článku. Pro úplnost připomenu, že pole je také objekt. No a při získávání hodnoty členské proměnné to bude zase naruby, tj. T nebude jako poslední argument funkce, ale jako návratový typ:

  • T GetTypField(jobject obj, jfieldID fieldID)
  • T GetTypField(jobject obj, jfieldID fieldID)
  • T GetStaticTypField(jobject obj, jfieldID fieldID)
  • T GetStaticTypField(jobject obj, jfieldID fieldID)

Voláme metody

link

Funkcí pro volání metod je zase celá velká sada. Máme možnost volat statické metody (T CallStaticTypMethod(...)) a nestatické metody (T CallTypMethod(...)). Jako Typ lze u metod kromě devíti výše uvedených typů použít i Void. Jsou tu ale ještě další speciality: můžeme volat nestatickou metodu s určením třídy, nebude se tedy brát v potaz tabulka virtuálních funkcí (T CallNonvirtualTypMethod(...). A konečně pak ještě máme tři různé způsoby, jak předávat argumenty. Jestli správně počítám, dává to celkem 90 funkcí, mezi kterými si musíme správně vybrat.

První způsob, jak předat argumenty, je předveden v ukázce na začátku článku. V tomto případě se použitá funkce JNI nazývá například CallVoidMethod a má variabilní počet argumentů:

void CallVoidMethod(jobject obj, jmethodID methodId, ...)

Logicky musíme předat správný počet argumentů! Jako poslední argument není potřeba dávat NULL (jako u execl()), protože podle ID metody je jasné, kolik argumentů byste měli předávat. Druhý způsob je dodat argumenty přes va_list – osobně mi to nepřijde moc užitečné, takže vás v této věci odkáži na manuálovou stránku STDARG(3).

void CallVoidMethodV(jobject obj, jmethodID methodId, va_list args)

A třetím způsobem, u kterého se na chvíli zastavíme, je předat pole hodnot typu jvalue:

void CallVoidMethodA(jobject obj, jmethodID methodId, jvalue* args)

jvalue má oproti va_list tu zásadní výhodu, že se dá velmi snadno dynamicky vytvářet. jvalue je definováno jako union:

typedef union jvalue {
    jboolean z;
    jbyte    b;
    jchar    c;
    jshort   s;
    jint     i;
    jlong    j;
    jfloat   f;
    jdouble  d;
    jobject  l;
} jvalue;

Užití jvalue si dovedu představit v různých wrapperech. Pro ukázku nám postačí něco snazšího, i když bychom se v tomto případě bez jvalue obešli. Zavoláme si známou metodu Integer.parseInt(String s, int radix):

jstring strBinary = env->NewStringUTF("1011010111");
jclass clsInteger = env->FindClass("java/lang/Integer");
jmethodId mParseInt = env->GetStaticMethodID(clsInteger, "parseInt", "(Ljava/lang/String;I)I");

jvalue args[2];
args[0].l = strBinary;
args[1].i = 2;

int result = env->CallStaticMethodA(clsInteger, mParseInt, args);

// v proměnné "result" bude 727

Ještě si ukážeme volání metody bez použití tabulky virtuálních funkcí. Nenapadá mě, jak přesně to samé udělat v Javě. Jen volání super.metoda() se tomuto přibližuje, i když v tomto případě si nemůžeme vybírat, jakou konkrétní třídu chceme použít. Ale nuže dobrá, předvedeme si obdobu super.metoda():

void metoda(JNIEnv* env, jobject jThis)
{
	// Získáme obdobu "super"
	jclass superClass = env->GetSuperclass(env->GetObjectClass(jThis));

	// Získáme ID aktuální metody
	jmethodID mMetoda = env->GetMethodID(superClass, "metoda", "()V");
	
	// Zavoláme
	env->CallNonvirtualVoidMethod(jThis, superClass, mMetoda);
}

A jak jste jistě správně pochopili, funkce CallNonvirtualVoidMethod je deklarována následovně:

void CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodId, ...)

Práce s poli

link

Práce s poli sice se zbytkem této lekce zdánlivě nesouvisí, ale má s ním něco společného. I pro práci s poli je spousta funkcí, které se liší používaným datovým typem. První funkcí je GetArrayLength(), které funguje u všech polí, odpovídá .length v Javě a funguje následovně:

int printLength(JNIEnv* env, jarray arr)
{
	jsize len = env->GetArrayLength(arr);
	std::cout << "Velikost pole je " << len << std::endl;
}

Pole primitivního typu vytvoříme pomocí jedné z funkcí void NewTypArray(jsize length). Pole objektů je trochu jiné, zde určujeme typ a počáteční hodnotu prvků:

void vytvorPole(JNIEnv* env, int length)
{
	jclass cls = env->FindClass("java/lang/String");
	jstring str = env->NewStringUTF("Ahoj");
	jarray arr = env->NewObjectArray(length, cls, str);

	env->SetObjectArrayElement(arr, 0, env->NewStringUTF("Čau!"));
}

Asi není třeba nic dodávat. U primitivních typů je to složitější, a to zejména díky tomu, že máme možnost do nich zapisovat nebo je číst efektivněji než položku po položce. Hlavní funkcí, která nám zpřístipní celé pole je tato:

T* GetTypArrayElements(jarray array, jboolean* isCopy)

Poslední argument můžeme nastavit na NULL. Je to jen informace pro nás, jestli JNI/JVM muselo vytvářet pro naše použití kopii pole. Pokud dostaneme odpověď JNI_FALSE, tak přímo zapisujeme do paměti javovského programu. V opačném případě se obsah nakopíruje zpět až po zavolání této funkce – a vězte, že je nutné ji zavolat vždy, bez ohledu na hodnotu isCopy:

void ReleaseTypElements(jarray array, T* data, jint mode)

mode je zajímavá hračka. Pokud zadáme 0, tak se data přenesou zpět do javovského programu a naše práce je u konce. Pokud jsme nic neměnili, můžeme použít konstantu JNI_ABORT, takže se vyvarujeme případnému kopírování položek, kdyby náhodou isCopy bylo JNI_TRUE. A poslední možností je JNI_COMMIT, kdy jsou data přenesena zpět do javovského programu (v ten moment máme záruku, že je program vidí), ale dáváme vědět, že s nimi ještě budeme pracovat – tedy že budeme Release volat ještě minimálně jednou.

void vytvorPolePlneNul(JNIEnv* env)
{
	// Vytvoříme pole
	jarray arr = env->NewIntArray(10);

	// Získáme céčkový ukazatel na pole
	jint* pArr = env->GetIntArrayElements(arr, 0);

	// Nastavíme hodnotu na nuly
	memset(pArr, 0, sizeof(jint)*10);

	// Vrátíme pole Javě
	env->ReleaseIntArrayElements(arr, pArr, 0);
}

Pokud z výkonnostních důvodů potřebujeme zvýšit šanci, že data nejsou mezi nativním a javovským programem kopírována, můžeme použít funkce GetPrimitiveArrayCritical a ReleasePrimitiveArrayCritical (tentokrát bez určení typu). Ještě než tak uděláte je ale vhodné přečíst si důkladně popis v dokumentaci, protože jsou zde takto omezení na to, co si nativní program může při své práci nad polem dovolit dělat.

Na závěr zmiňme ještě dvojici GetTypArrayRegion a SetTypArrayRegion. Při jejich použití nemusíme získávat přístup k celému poli, nýbrž jen k jeho části.

Co bude příště

link

Příště se podíváme ještě na nějaké zbývající drobnosti. Pak už přijde řada na JNA.

       

Hodnocení: 91 %

        špatnédobré        

Nástroje: Tisk bez diskuse

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

Komentáře

Vložit další komentář

30.12.2017 14:36 Sample
Rozbalit Rozbalit vše Re: Java Native Interface – voláme Javu z nativního kódu a ještě více
6.1. 12:49 Cisco Customer Support
Rozbalit Rozbalit vše Re: Java Native Interface – voláme Javu z nativního kódu a ještě více
Useful Information You have the nice information thanks for sharing. If you need Asus router customer service Help Use Our Service.
22.3. 11:16 harryjames
Rozbalit Rozbalit vše Re: Java Native Interface – voláme Javu z nativního kódu a ještě více
nice article thank you <www.driversin.com
30.6. 07:25 leeku
Rozbalit Rozbalit vše Re: Java Native Interface – voláme Javu z nativního kódu a ještě více
wellhttp://vidmateinstalldownload.com/ http://vidmateinstall.org/ http://vidmateapk.info http://vidmateapk.net.in/ http://vidmateapk.org.in/ http://vidmateinstall.in http://vidmatedownloader.org http://vidmateinstall.org http://vidmateoldversion.co.in/ http://vidmateapp.net.in/
30.6. 07:27 leeku
Rozbalit Rozbalit vše Re: Java Native Interface – voláme Javu z nativního kódu a ještě více
30.6. 07:28 leeku
Rozbalit Rozbalit vše Re: Java Native Interface – voláme Javu z nativního kódu a ještě více
30.6. 07:28 leeku
Rozbalit Rozbalit vše Re: Java Native Interface – voláme Javu z nativního kódu a ještě více
30.6. 07:29 leeku
Rozbalit Rozbalit vše Re: Java Native Interface – voláme Javu z nativního kódu a ještě více
30.6. 07:29 leeku
Rozbalit Rozbalit vše Re: Java Native Interface – voláme Javu z nativního kódu a ještě více

Založit nové vláknoNahoru

ISSN 1214-1267   www.czech-server.cz
© 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.