如何以 JAVA call 一個現有的 dll 檔?

如何以 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: 已經記錄

 

Old Post 06-10-2003 08:07 AM
johnson 離線中 點擊這裡查看 johnson 的個人資料 點擊這裡給 johnson 發送悄悄話 搜尋更多 johnson 的文章 增加 johnson 到您的好友名單中 編輯/刪除文章 回覆/引用
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: 已經記錄

 

Old Post 06-11-2003 05:27 AM
Duncan 離線中 點擊這裡查看 Duncan 的個人資料 點擊這裡給 Duncan 發送悄悄話 搜尋更多 Duncan 的文章 增加 Duncan 到您的好友名單中 編輯/刪除文章 回覆/引用
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: 已經記錄

 

Old Post 06-11-2003 07:47 AM
Duncan 離線中 點擊這裡查看 Duncan 的個人資料 點擊這裡給 Duncan 發送悄悄話 搜尋更多 Duncan 的文章 增加 Duncan 到您的好友名單中 編輯/刪除文章 回覆/引用
johnson
初級會員

註冊日期: Apr 2003
居住地:
共發表: 7 篇文章

 


本主題第 4 篇文章

 

 

不快樂/Unhappy 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: 已經記錄

 


Old Post 06-12-2003 10:45 AM
johnson 離線中 點擊這裡查看 johnson 的個人資料 點擊這裡給 johnson 發送悄悄話 搜尋更多 johnson 的文章 增加 johnson 到您的好友名單中 編輯/刪除文章 回覆/引用
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: 已經記錄

 

Old Post 06-12-2003 03:30 PM
Duncan 離線中 點擊這裡查看 Duncan 的個人資料 點擊這裡給 Duncan 發送悄悄話 搜尋更多 Duncan 的文章 增加 Duncan 到您的好友名單中 編輯/刪除文章 回覆/引用
johnson
初級會員

註冊日期: Apr 2003
居住地:
共發表: 7 篇文章

 


本主題第 6 篇文章

 

 

談話/Talking 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

posted on 2009-12-15 15:12  cy163  阅读(3405)  评论(0编辑  收藏  举报

导航