如何以 JAVA call 一個現成的 dll 檔?
http://ehome.hifly.to/showthread.php?threadid=750
版主大大您好,小弟又有問題要向您討教。 問題: 老闆拿來一支 dll 檔,是控制印表機用的。 但附的 sample 是以 VB6.0 所寫的,程式宣告方式: Public Declare Function UTL_T28_Enable Lib "utlt" () As Long Public Declare Function UTL_T28_Disable Lib "utlt" () As Long 要用直接用: dim RESPON as Long RESPON = UTL_T28_Enable RESPON = UTL_T28_Disable
現在該如何以 java call 這個 dll 檔呢? 小弟看書及找資料,發現: 1、寫一支 java 程式,編譯成 class 檔,例如: class HelloWorld { public native void displayHelloWorld(); static {System.loadLibrary("hello");} public static void main(String[] args) {new HelloWorld().displayHelloWorld();} }
2、用 javah -jni HelloWorld ,生成 HelloWorld.h 檔 #include <jni.h> #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);
#ifdef __cplusplus } #endif #endif
3、寫 C 程式,method name 要與 java 的 method name 相對應,編譯成 dll 檔 #include <jni.h> #include "HelloWorld.h" #include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj) { printf("Hello world!\n"); return; }
一般的書都介紹到此。 可是如果 dll 檔像小弟所遇到的,它已經寫好了,也沒有包括下列三行時: #include <jni.h> #include "HelloWorld.h" #include <stdio.h> 結果是沒辦法以 java call 它,即使 method name 相對應。 不知版主大大能不能給小弟一點建議,謝謝。
反應文章 | IP: 已經記錄
|
06-10-2003 08:07 AM |
|
|
|
|
|
Duncan 版主
註冊日期: Nov 2002 居住地: 高雄市 共發表: 263 篇文章
|
本主題第 2 篇文章
Re: 如何以 JAVA call 一個現成的 dll 檔?
quote:
原發表者是 johnson 版主大大您好,小弟又有問題要向您討教。 問題: 老闆拿來一支 dll 檔,是控制印表機用的。 但附的 sample 是以 VB6.0 所寫的,程式宣告方式: Public Declare Function UTL_T28_Enable Lib "utlt" () As Long Public Declare Function UTL_T28_Disable Lib "utlt" () As Long 要用直接用: dim RESPON as Long RESPON = UTL_T28_Enable RESPON = UTL_T28_Disable
現在該如何以 java call 這個 dll 檔呢? 可是如果 dll 檔像小弟所遇到的,它已經寫好了,也沒有包括下列三行時: #include <jni.h> #include "HelloWorld.h" #include <stdio.h> 結果是沒辦法以 java call 它,即使 method name 相對應。 不知版主大大能不能給小弟一點建議,謝謝。
你沒有辦法把已寫好的 dll 模組裡的 function 直接當作 native method,因為 JNI 對 native method 的 signature 有特殊的規定,method name start with Java、first parameter is JNIEnv* 等等。
但是不代表你就不能使用這些 dll,你可以自己寫一個 wrapper class 提供數個 native method,而這些 native method 的 implementation 則是去 call dll export 出來的 function,前提是你要知道 dll export 出來的 function name and prototype,名字可以使用 VC tool: dumpbin.exe:
dumpbin -exports a_dll.dll
從你 post 的 usage 來看,我猜 UTL_T28_Enable/UTL_T28_Disable 都是 Long (*)(),至於 VB Long type 是否可以 map to C long 我不清楚,事實上我看不懂 VB,只看的懂古早時代的 BASIC。
在 Java native method 實做中,你可以透過 win32 API LoadLibrary 來載入 dll,再透過另一 win32 API GetProcAddress 來取得某個 function 的 address,你將傳回位址專為適當的 pointer to function 就可以透過 pointer 來 invoke 之。
code: FARPROC GetProcAddress( HMODULE hModule, // handle to DLL module LPCSTR lpProcName // function name);HMODULE LoadLibrary( LPCTSTR lpFileName // file name of module);
__________________ 給我 辣味豆腐--------------Davidoff 其餘免談
反應文章 | IP: 已經記錄
|
06-11-2003 05:27 AM |
|
|
|
|
|
Duncan 版主
註冊日期: Nov 2002 居住地: 高雄市 共發表: 263 篇文章
|
本主題第 3 篇文章
Re: Re: 如何以 JAVA call 一個現成的 dll 檔?
quote:
原發表者是 Duncan
在 Java native method 實做中,你可以透過 win32 API LoadLibrary 來載入 dll,再透過另一 win32 API GetProcAddress 來取得某個 function 的 address,你將傳回位址專為適當的 pointer to function 就可以透過 pointer 來 invoke 之。
舉個例子,以 JNI 來執行 user32.dll - MessageBoxA(就是 win32api - MessageBox):
code: // MB.javapublic class MB{public native static void showMessage();static{System.loadLibrary("JavaMB");}}// MB.cpp#include "MB.h"typedef int (__stdcall * Func)(HWND, LPCTSTR, LPCTSTR, UINT);extern "C" JNIEXPORT voidJNICALL Java_MB_showMessage(JNIEnv *, jclass){const char* dllName = "user32.dll";const char* funcName = "MessageBoxA";HINSTANCE hComp = ::LoadLibrary(dllName);if (hComp == 0){cout << "Error: Can't load " << dllName << endl;return;}Func aFunc = (Func)::GetProcAddress(hComp, funcName);if (aFunc == 0){cout << "Cannot find " << funcName << " function!"<< endl;return;}aFunc(0, "A message from MB.showMessage.", "A System-modal message box", MB_OK | MB_ICONINFORMATION | MB_SYSTEMMODAL);}
製作出 JavaMB.dll 之後放到 java.library.path 路徑之中,寫一個 Java application invoke MB.showMessage()。
__________________ 給我 辣味豆腐--------------Davidoff 其餘免談
Duncan 在 06-11-2003 07:51 AM 編輯
反應文章 | IP: 已經記錄
|
06-11-2003 07:47 AM |
|
|
|
|
|
johnson 初級會員
註冊日期: Apr 2003 居住地: 共發表: 7 篇文章
|
本主題第 4 篇文章
Re: Re: 如何以 JAVA call 一個現成的 dll 檔?
quote:
原發表者是 Duncan
你沒有辦法把已寫好的 dll 模組裡的 function 直接當作 native method,因為 JNI 對 native method 的 signature 有特殊的規定,method name start with Java、first parameter is JNIEnv* 等等。
但是不代表你就不能使用這些 dll,你可以自己寫一個 wrapper class 提供數個 native method,而這些 native method 的 implementation 則是去 call dll export 出來的 function,前提是你要知道 dll export 出來的 function name and prototype,名字可以使用 VC tool: dumpbin.exe:
dumpbin -exports a_dll.dll
從你 post 的 usage 來看,我猜 UTL_T28_Enable/UTL_T28_Disable 都是 Long (*)(),至於 VB Long type 是否可以 map to C long 我不清楚,事實上我看不懂 VB,只看的懂古早時代的 BASIC。
在 Java native method 實做中,你可以透過 win32 API LoadLibrary 來載入 dll,再透過另一 win32 API GetProcAddress 來取得某個 function 的 address,你將傳回位址專為適當的 pointer to function 就可以透過 pointer 來 invoke 之。
code: FARPROC GetProcAddress( HMODULE hModule, // handle to DLL module LPCSTR lpProcName // function name);HMODULE LoadLibrary( LPCTSTR lpFileName // file name of module);
反應文章 | IP: 已經記錄
|
06-12-2003 10:45 AM |
|
|
|
|
|
Duncan 版主
註冊日期: Nov 2002 居住地: 高雄市 共發表: 263 篇文章
|
本主題第 5 篇文章
Re: Re: Re: 如何以 JAVA call 一個現成的 dll 檔?
quote:
原發表者是 johnson
非常感謝版主大大的回答。 這兩天小弟找了許多資料,並參考版主大大的回答,結論: 自己寫一個 wrapper class : 這個...........,有困難,因為小弟不懂 C及C++。 所以, 小弟用 VB 把這個 DLL 包成 ActiveX,如此 JavaScript 可用。(先頂著用) 然後找工具, IBM Bridge2Java ,可讓 JAVA 與 ActiveX 溝通。不過有問題。
xfunction ,一個 jar file,可讓 JAVA 與 DLL 溝通。還在測。
jawin ,搭配 ant 和 Junit ,可讓 JAVA 與 DLL 溝通。還在測。
其實根本之道,還是要學 C及C++。 只是目前正在趕,只好先找工具。 在這裡,實在非常感謝版主大大的回答與建議,使小弟找對方向,再次感謝。
你不懂 C/C++?可是我看你好像有接觸 JNI,以為........
你有沒有用過 MS SDK for Java?我想你可以考慮一下,使用 SDK for Java(不知道還找不找的到) 你可以在 Java application 裡使用 ActiveX control,而且蠻容易做到的,但有個缺點是其使用的 Java core classes 只到 1.1.x,所以你若使用了 SDK for Java 當作 solution,你就沒辦法與已存的 JDK1.2+ 所發展出來的部分整合。
我以 Calendar 元件作個 example:
code: // DemoX.javaimport java.awt.BorderLayout;import java.awt.Button;import java.awt.Font;import java.awt.Frame;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import com.ms.activeX.ActiveXControl;public class DemoX{public static void main(String[] args){Frame frm = new Frame("Demo for ActiveX control.");frm.setBounds(100, 100, 500, 400);frm.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}});final ActiveXControl ctl = new ActiveXControl(ProgID); // or CLSIDfrm.add(ctl, BorderLayout.CENTER);Button prop = new Button("Open property sheet");prop.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){ctl.showPropertyDialog();}});frm.add(prop, BorderLayout.SOUTH);frm.show();}// dependent on the ocx install on your computerprivate static String ProgID = "MSCAL.Calendar.7";private static String CLSID = "{8E27C92B-1264-101C-8A2F-040224009C02}";}
compilation: jvc demox.java
execute: wjview DemoX
__________________ 給我 辣味豆腐--------------Davidoff 其餘免談
反應文章 | IP: 已經記錄
|
06-12-2003 03:30 PM |
|
|
|
|
|
johnson 初級會員
註冊日期: Apr 2003 居住地: 共發表: 7 篇文章
|
本主題第 6 篇文章
Re: Re: Re: Re: 如何以 JAVA call 一個現成的 dll 檔?
quote:
原發表者是 Duncan
你不懂 C/C++?可是我看你好像有接觸 JNI,以為........
你有沒有用過 MS SDK for Java?我想你可以考慮一下,使用 SDK for Java(不知道還找不找的到) 你可以在 Java application 裡使用 ActiveX control,而且蠻容易做到的,但有個缺點是其使用的 Java core classes 只到 1.1.x,所以你若使用了 SDK for Java 當作 solution,你就沒辦法與已存的 JDK1.2+ 所發展出來的部分整合。
我以 Calendar 元件作個 example:
code: // DemoX.javaimport java.awt.BorderLayout;import java.awt.Button;import java.awt.Font;import java.awt.Frame;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import com.ms.activeX.ActiveXControl;public class DemoX{public static void main(String[] args){Frame frm = new Frame("Demo for ActiveX control.");frm.setBounds(100, 100, 500, 400);frm.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}});final ActiveXControl ctl = new ActiveXControl(ProgID); // or CLSIDfrm.add(ctl, BorderLayout.CENTER);Button prop = new Button("Open property sheet");prop.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){ctl.showPropertyDialog();}});frm.add(prop, BorderLayout.SOUTH);frm.show();}// dependent on the ocx install on your computerprivate static String ProgID = "MSCAL.Calendar.7";private static String CLSID = "{8E27C92B-1264-101C-8A2F-040224009C02}";}
compilation: jvc demox.java
execute: wjview DemoX
|
|
|