跳到主要內容

JNI(Java Native Interface) Learning Notes

JNI Learning Notes

要從Java中呼叫第三方C的DLL, cstat.dll,該程式沒有source code無法重新編譯。
因JNI的方式來呼叫的話,C的函數名稱有固定的規則,因為無cstat.dll的原始檔可以修改,因此要用C/C++寫一個中間程式來呼叫cstat.dll。
架構為
Java Class -> intermedia c program -> cstat.dll
( ->代表函數呼叫 )

產生C header file
javah -jni Hello
produce Hello.h

C compiler
Download free cygwin
安裝時要選擇gcc的套件一併安裝,才有gcc可用。

編譯出object file,
要求編譯系統不要使用 cygwin的DLL
gcc -c -I C:/j2sdk1.4.2_13/include -I C:/j2sdk1.4.2_13/include/win32 -mno-cygwin Sample1.c
-c 執行編譯
-I 指定jni.h的目錄位置與作業系統相關的header file位置

Build DLL from .o file
gcc -shared -o
Sample1.dll Sample1.o
製作 DLL 時要求編譯系統不要使用 cygwin 的 DLL

gcc -mno-cygwin -shared -o HelloImp.dll HelloImp.o

Build DLL directly from .c file
gcc -shared -mno-cygwin -I C:/j2sdk1.4.2_13/include -I C:/j2sdk1.4.2_13/include/win32 Arguments.c -o Arguments.dll

Final correct command with options
gcc -shared -mno-cygwin -Wl,--kill-at -I C:/j2sdk1.4.2_13/include -I C:/j2sdk1.4.2_13/include/win32 Arguments.c -o Arguments.dll

-Wl,option
把option傳遞給連接器,如果option中含有逗號,就在逗號處分割成多個選項

from JavaWorld 有人寫到:
在Windows下用gcc編譯可被JNI呼叫的dll檔要這樣下:
gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I/java/include -I/java/include/win32 -shared -o JavaImp.dll someJavaImp.c
我用的是MinGW

經過我測試 不加
-D_JNI_IMPLEMENTATION_也可以運作,事實上我在gcc的手冊中找不到這個option
我也找不到--kill-at這個option。

Load DLL in C++

#include
HINSTANCE fhandle= LoadLibrary("CSTAT.DLL");

HINSTANCE is defined in windows.h
[BCB help]
HINSTANCE, Indicates the handle provided by Windows for an application or library.
The LoadLibrary function maps the specified executable module into the address space of the calling process.
If the function succeeds, the return value is a handle to the module.
If the function fails, the return value is NULL.
typedef __stdcall(*Functiontype)(int) //first define function type, int is received argutment list
afunction = (
Functiontype)GetProcAddress(fhandle, "afunction_name");[BCB help]
The GetProcAddress function returns the address of the specified exported dynamic-link library (DLL) function.
FARPROC GetProcAddress(
HMODULE hModule, // handle to DLL module
LPCSTR lpProcName // name of function
);

問題
找不到程序進入點,在cygwin1.dll
此問題可透過編譯時加上-mno-cygwin來移除cygwin DLL的相依性


Exception in thread "main" java.lang.UnsatisfiedLinkError: hello
at Hello.main(Hello.java:9)


Exception in thread "main" java.lang.UnsatisfiedLinkError: no Sample1 in java.li
brary.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1290)
at java.lang.Runtime.loadLibrary0(Runtime.java:473)
at java.lang.System.loadLibrary(System.java:777)
at Sample1.main(Sample1.java:10)
找不到所需的dll,確認系統環境變數PATH中有包含dll所在的目錄。

Exception in thread "main" java.lang.UnsatisfiedLinkError: D:\Hawk\workspace\Jni
\Sample1.dll: The specified procedure could not be found
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1360)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1284)
at java.lang.Runtime.loadLibrary0(Runtime.java:473)
at java.lang.System.loadLibrary(System.java:777)
at Sample1.main(Sample1.java:10)

相關書籍:
Java深度歷險, 王森, McGrawHill

留言

這個網誌中的熱門文章

iframe DOM 被移動造成重新載入

如果用 javascript 去搬動 iframe DOM 的位置, 瀏覽器會將其內容重新載入,這是現有 HTML 規格 > When an iframe element is inserted into a document that has a browsing context, the user agent must create a nested browsing context, and then process the iframe attributes for the "first time". 範例: http://jsfiddle.net/pZ23B/ 測試結果: * Safari 3.1 / Win: reload * Opera 9.5 / Win: reload * IE10: reload * IE7 / IE8: not reload (部份摘自 https://bugzilla.mozilla.org/show_bug.cgi?id=254144 ) 參考: * https://bugzilla.mozilla.org/show_bug.cgi?id=254144

ZK 與響應式網頁設計(RWD)

響應式網頁設計 (RWD) 就現今而言應該是許多網站必備的條件之一,ZK 框架可以幫你從一個抽象層次較高的角度滿足 RWD,不需要了解 CSS Media Query 的細節。 元件層級 元件層級的 RWD 是由元件內部自動完成的。每個 ZK 元件都能區分瀏覽器的種類,因此會自動依據桌上型或行動裝置瀏覽器來自動調整元件的外觀,不需開發者介入,例如 datebox 在桌面瀏覽器會跳出小月曆: 在手機瀏覽器就會自動變成下方滾動條: 頁面層級 頁面層級的 RWD 因為牽涉到版面設計,因此無法靠元件自動完成,因為畢竟每個頁面需要的版面設計皆不相同,這通常不是一個技術性的決定,而是政策性或設計性上的決定,因此 ZK 提供一些工具讓你實現 RWD。以下根據你想要達成的效果,概述你可用的工具。 寬度、版面自動調整 如果你想要做出的效果是,畫面內各區域自動調整寬度,較窄時調整位置,我非常推薦搭配 Bootstrap Grid 與 ZK 一同使用,因為 易於整合 。使用 Grid system 只要在 div 套上 CSS class,如 col-md-4 ,因此跟 ZK 整合很容易,不需要特別的設定與程式。 元件變換 如果你希望畫面寬、窄時,各用不同的元件來顯示,例如側邊欄在畫面變窄時消失並換成小的選單圖示,這時元件本身當然無法得知要做這樣的轉換,你可以透過 onClientInfo 事件 或 @MatchMedia 來偵測畫面寬度變化,並針對該變化調整畫面元件。 更多細節可以參考以下資源: Use Bootstrap with ZK: Responsive Admin Template 範例專案 線上展示