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
要從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
留言