• 如何以 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

  • 相关阅读:
    c++设计模式总结
    Java复习(四)类的重用
    Java复习(三)类中的方法
    Java复习(二)类与对象的基本概念
    Java复习(一)——Java语言概述、开发环境、基础知识
    Java复数的加乘除运算
    人见人爱A+B
    noj快排
    noj最长公共子序列
    C语言里有没有sort函数?有!
  • 原文地址:https://www.cnblogs.com/cy163/p/1624833.html
Copyright © 2020-2023  润新知