<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.grejpfrut.org &#187; jni</title>
	<atom:link href="http://grejpfrut.org/blog/tag/jni/feed/" rel="self" type="application/rss+xml" />
	<link>http://grejpfrut.org/blog</link>
	<description>a DRY KISS</description>
	<lastBuildDate>Fri, 22 Jan 2010 20:58:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>JNI</title>
		<link>http://grejpfrut.org/blog/2007/02/11/jni/</link>
		<comments>http://grejpfrut.org/blog/2007/02/11/jni/#comments</comments>
		<pubDate>Sun, 11 Feb 2007 09:17:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[po polsku]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[jni]]></category>

		<guid isPermaLink="false">http://maneo.webd.pl/blog/?p=25</guid>
		<description><![CDATA[Od dłuższego czasu chciałem przyjrzeć się i chociażby koniuszkiem palców dotknąć JNI. Nie sięgnąłem po JNI z własnej woli, jak wiadomo JNI jest środkiem ostatecznym, czymś do czego odwołujemy się gdy brak już nadziei, gdy wszystkie mosty są spalone i próżno wypatrywać choćby najmniejszego “słoika” z remedium na nasze problemy. Właśnie w takich chwilach programiści [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Od dłuższego czasu</strong> chciałem przyjrzeć się i chociażby koniuszkiem palców dotknąć JNI. Nie sięgnąłem po JNI z własnej woli, jak wiadomo JNI jest środkiem ostatecznym, czymś do czego odwołujemy się gdy brak już nadziei, gdy wszystkie mosty są spalone i próżno wypatrywać choćby najmniejszego “słoika” z remedium na nasze problemy. Właśnie w takich chwilach programiści Javy wpisują w wyszukiwarkę te trzy magiczne literki <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .  W kilku akapitach opowiem o tym na co warto zwrócić uwagę  i gdzie natknąłem się na problemy, może to komuś pomoże.</p>
<p><strong>Aby stworzyć wiązanie</strong> będziemy musieli przejść przez kilka etapów pośrednich.</p>
<ul>
<li> Będziemy musieli zdefiniować interfejs programistyczny w Javie,</li>
<li> następnie przygotować na odpowiednie pliki nagłówkowe dla implementacji w C/C++ .</li>
<li> w końcu przyjdzie czas na trochę prawdziwej implementacji. Będzie okazja, żeby sprawdzić ile pamiętasz z C/C++ <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</li>
</ul>
<p><strong>Stworzenie API Javowego</strong> to rzecz najprostsza, znajdziecie to w każdym tutorialu np. <a href="http://www.codeproject.com/java/jnibasics1.asp">tutaj</a>. Wydaje mi się, że nawet nie trzeba tego arta dokładnie czytać <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> , jeżeli chodzi o Javo’ową stronę najważniejsze są dwie rzeczy:</p>
<ul>
<li> Słówko <code>native</code> które informuję kompilator, że implementację tej metody dostarczy zewnętrzna biblioteka natywna. Przykładowa sygnatura metody:  <code>private native void sayHello();</code>.</li>
<li> Druga sprawa to załadowanie natywnej biblioteki do naszego projektu (już po uruchomieniu), zrealizować to można poprzez następujący statyczny blok kodu:
<pre class="brush: java;">
static {
  System.load(&quot;ścieżka\HelloWorldNative\dist\HelloWorldNative.dll&quot;);
 }
</pre>
<p>Możemy użyć metody <code>load</code> lub <code>loadLibrary</code> różnica między nimi może okazać się istotna. W wywołaniu metody <code>load</code> podajemy dokładną nazwę biblioteki wraz z rozszerzeniem. Wystarczy wyobrazić sobie sytuację gdy chcemy nasz program uruchomić pod linuxem, biblioteka zamiast rozszerzenia .dll ma .so. Z pomocą przychodzi nam druga wspomniana metoda,  <code>loadLibrary</code> przyjmuję na wejściu tylko nazwę biblioteki (bez rozszerzenia), odpowiednia biblioteka jest wyszukiwana przez jvm w lokalizacjach na które wskazuje zawartość property systemowego <code>java.library.path</code>. Standardowo do <code>java.library.path</code> dodawane są (dla Windows) katalogi <code>../Windows</code> oraz <code>../Windows/System32</code> powinien również zostać  uwzględniony biezący katalog w którym jest uruchamiana aplikacja Javowa korzystająca z biblioteki.Więcej o wspomnianych metodach w  dokumentacji klasy <a href="http://java.sun.com/j2se/1.3/docs/api/java/lang/System.html">System</a>.</li>
</ul>
<p><strong>Gdy mamy gotowy</strong> kod javowy, możemy wygenerować sobie plik(i) nagłówkowy które posłużą nam do implementacji kodu w C/C++.</p>
<pre>      javah.exe -o wyjsciowy.h -jni -classpath ścieżka-do-klasybuildclasses NaszaKlasa</pre>
<p>Należy przy tym pamiętać, że <code>javah</code> działa na skompilowanej klasie, więc jeżeli zmienisz coś w kodzie, pamiętaj aby najpierw zmienioną klasę skompilować a dopiero potem wywołać powyższe  polecenie po raz drugi.</p>
<p><strong>Finalnym i najbardziej pracochłonnym</strong> krokiem jest stworzenie natywnej biblioteki pośredniczącej. Biblioteka taka musi oferować funkcje określone w wygenerowanym w poprzednim kroku pliku nagłówkowym. Omówię skrótowo jak to zrobiłem w Visual Studio 2005, polecam też:<a href="http://www.netbeans.org/kb/55/beginning-jni-part1.html">Beginning JNI with NetBeans C/C++ Pack 5.5</a>, jeżeli zdecydujecie się użyć opisanego w tutorialu zestawu Netbeans+Cygwin może wam się przydać informacja o tym, że GCC nie obsługuje (win32+cygwin) typu “__int64″. Został użyty w deklaracji typu w plikach nagłówkowych jni, na <a href="http://www.graphics-muse.org/wp/?page_id=147">The  Graphic Muse</a> znajdziecie dokładniejsze wytłumaczenie, wraz z eleganckim rozwiązaniem problemu <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Przejdźmy jednak do rzeczy:</p>
<ol>
<li> Stwórz projekt:File/NewProject/Win32Project/ po wprowadzeniu nazwy przejdziesz do dalszych stron wizarda,  wybierz: <strong>DLL</strong> jako typ aplikacji i zaznacz checkbox “Export symbols”.  Zatwierdź wszystko.</li>
<li> Teraz będzie trochę mieszania <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  w właściwościach projektu, kliknij prawym na głównym węzeł projektu w “Solution Explorer”. Musimy  dodać do naszego projektu katalogi z których Visual Studio ma brać pliki nagłówkowe związane z JNI.  W <code>Configuration Properties/C/C++/General/Additional Includes Directories</code> dodajemy dwa katalogi: <code>JAVAHOME/include</code> oraz <code>JAVAHOME/include/windows</code>. Dodajemy również  katalog  w którym znajduję się wygenerowany przez nas plik nagłówkowy.</li>
<li> Czas w końcu uwzględnić bibliotekę do której wiążemy nasz kod javowy. Ja otrzymałem wraz z plikiem <strong>.dll</strong>,  plik <strong>.lib</strong> oraz odpowiedni plik nagłówkowy <strong>.h</strong>. Plik nagłówkowy dodajemy analogicznie jak w poprzednim kroku, natomiast  .lib należy uwzględnić w własnościach linkera (<code>Linker/Input/Additional Dependencies</code>).</li>
<li> W projekcie istnieje plik nazwa-projektu.cpp, właśnie w nim będzie się działo całe zło <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .
<pre class="brush: java;">
    #include &quot;jni.h&quot;
    #include &quot;windows.h&quot;
    #include &quot;plik-naglowkowy-natywnej-biblioteki.h&quot;
    #include &quot;wygenerowany-przez-nas-plik-naglowkowy.h&quot;
</pre>
<p>Pozostaje “tylko” zaimplementować odpowiednie funkcje w C++.</li>
</ol>
<p><strong>Jeżeli chodzi o implementację</strong> należy zwrócić uwagę na kilka istotnych kwestii:</p>
<ul>
<li> W C/C++ łańcuchy tekstowe (String) nie są kodowane w utf-8 jak w Javie, o tym jak to robić poprawnie można <a href="http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jnistring.html#string">poczytać tu</a>.</li>
<li> Pamiętaj o tym, że każdy kawałek pamięci który zaalokujesz musisz zwolnić. Kod który piszesz będzie uruchomiony przez proces JVM, ale  łapska GC tu nie sięgają.</li>
<li> Odwoływanie się do tablic też nie jest takie proste… tu nic nie jest “taki proste” <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<p>VS2005 domyślnie buduje wersję <code>debug</code> naszego projektu, nalezy pamiętać, ze tak stworzony dll jest zależny od specyficznych bibliotek dostarczanych tylko z Visual Studio.</p>
<p><strong>Moja wiedza</strong> jak widzicie jest dość powierzchowna, ale jak zwykle mam nadzieje, że komuś to pomoże. W moim przypadku implementacja wiązania ograniczyła się do wywołania odpowiednich funkcji z oryginalnej dll’ki, mimo, że nie było tam wielkiej filozofii to i tak to co napisałem nie zawsze działa :/. Po wiedzę konkretną odsyłam do źródeł:</p>
<ul>
<li> <strong>“The Java  Native Interface &#8211; Programmer’s Guide and Specification”</strong> Sheng Liang</li>
<li> <a href="http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jni.html">JNI Technology</a> &#8211; Sun’owski tutorial, całkiem sporo przykładów.</li>
<li> <a href="http://www.netbeans.org/kb/55/beginning-jni-part1.html">Beginning JNI with Netbeans</a> &#8211; wspomniany w tekście tutorial: JNI w Netbeans.</li>
<li> <a href="http://www.graphics-muse.org/wp/?page_id=147">The  Graphic Muse</a> &#8211; krok po kroku, coś jak tutaj <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li> <a href="http://www.codeproject.com/java/jnibasics1.asp">JNI Basics &#8211; 1</a></li>
<li> <a href="http://www.codeproject.com/cpp/integratingcppjava.asp">Integrating Visual C++,Java and Assembly</a> &#8211; java i asm  (grrr…. <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )</li>
<li> <a href="http://www.codetoad.com/java_simpleJNI.asp">JNI tutorial</a></li>
</ul>
<p>Na sam koniec <strong>zostawiłem deser</strong>, jeżeli szukaliście kiedyś narzędzia do rozwiązywania nierozwiązywalnych problemów to <a href="http://www.swig.org/index.html">SWIG</a> jest właśnie dla was.  W skrócie:<br />
<em><br />
<strong>SWIG</strong> is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. SWIG is used with different types of languages including    common scripting languages such as Perl, PHP, Python, Tcl, Ruby and PHP.</em></p>
<p><strong>Poniżej update który zawdzięczamy w całości Przemkowi Lewickiemu (lemekk</strong>):</p>
<p>Ponieważ maneo “trzasnął” kawałek dobrego posta, który w moim przypadku okazał się bardzo pomocny, postanowiłem dorzucić od siebie kilka drobnych uwag, które mogą się komuś przydać przy walce z JNI <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p><strong>Wykorzystanie bibliotek typów.</strong><br />
W moim przypadku, musiałem wywołać funkcję znajdującą się w windowsowej bibliotece typów (konkretnie activeds.dll). I tu zaczęły się schody, ponieważ nie było już tak prosto jak w opisie maneo <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Do biblioteki dołączony jest tylko plik .tlb. I to właśnie nim należy się posłużyć, żeby wykorzystać bibliotekę. jest to jednak trochę bardziej skomplikowane niż proste zaincludowanie pliku nagłówkowego. Oto krótka proceudurka:</p>
<ul>
<li> w miejscu, gdzie dołączamy pliki nagłówkowe, zamiast zwykłego #import wklepujemy coś takiego: #include “biblioteka.tlb”</li>
<li>kompilujemy projekt. Kompilator powinien wygenerować kilka nowych plików w tym plik “biblioteka.tlh”.</li>
<li>w miejscu #include’a wpisujemy juz zwykły: #import “biblioteka.tlh” (prawdopodobnie plik “biblioteka.tlh” będzie trzeba przenieść wcześniej z folderu ‘debug’ do folderu projektu). W trakcie kompilacji mogą wystąpić błędy związane z powtórzeniem definicji typów. Trzeba wtedy po prostu usunąć te definicje z pliku “biblioteka.tlh”.</li>
</ul>
<p>Po takich akrobacjach powinniśmy już mieć dostęp do typów i ich funkcji w bibliotece.</p>
<p><strong>Błąd: “Exception in thread “main” java.lang.UnsatisfiedLinkError: ścieżka\NaszaBiblioteka.dll:</strong><br />
Nie można uruchomić aplikacji, ponieważ jej konfiguracja jest niewłaściwa. Problem ten może rozwiązać ponowne zainstalowanie aplikacji”. Błąd ten występował podczas ładowania biblioteki przez Javę, na komputerach, na których nie zainstalowany został Visual. Z rozwiązaniem tego problemu pomógł mi… maneo <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> , a piszę o tym dlatego, że nie umieścił tego w swoim poście bo pewnie było to dość oczywiste ale dla amatorów Visuala takich jak ja pewnie już nie <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . W każdym razie chodzi o konfigurację uruchomieniową (czy jak to tam zwał), z którą kompilator Visuala tworzy bibliotekę. Jak napisał maneo, domyślnie jest to konfiguracja “debug”. Czego nie napisał, to to, że należy wybrać konfigurację “release” <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Po takim zabiegu biblioteka powinna już “śmigać” wszędzie <img src='http://grejpfrut.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://grejpfrut.org/blog/2007/02/11/jni/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
