2010-03-05 571 views
32

我需要從Java程序中調用some methods in Wininet.dll從Java調用Win32 API方法

我可以找到大量關於如何調用從Java創建的新DLL的教程,但似乎找不到有關如何從Java調用已經存在的DLL的教程。

我知道這涉及到JNI,但是我該怎麼做呢?我需要在Wininet.h上調用javah嗎?我在哪裏可以獲得Wininet.h的副本?一個指向現有的,詳細教程就足夠了。

回答

38
  1. JNA似乎你想要什麼the industry standard,「提供Java程序方便地訪問本地共享庫(在Windows DLL)的無寫什麼,但基於Java的代碼沒有JNI或本機代碼需要」

  2. 還有Java Foreign Function Interface - example usage
    如果是確定FO R您,您可以embedJRuby解釋,並通過jruby-ffi至極是一個容易得多調用WINAPI,見hereherehere

+2

這需要一個凹凸 - JNA遠遠優於純JNI,用於本地庫訪問 – 2010-03-05 19:47:28

+0

+1:JNA是不錯的選擇雖然你需要弄清楚如何在Java中映射函數簽名,但我最近使用JNA與藍牙設備通過原生的Win32 API – wierob 2010-03-05 20:06:44

+0

JNA非常漂亮當我在一週的工作中向一位朋友解釋它時,我竟然竟然告訴他這是「魔術」。 – rob 2010-03-06 00:40:04

3

不能直接調用本地庫:這是因爲Java本地接口不支持方法中的某些參數。

有一種叫GlueGen的東西,它會創建一個獨立的二進制文件,它將動態鏈接到你的本地DLL。生成的二進制文件與JNI兼容,因此可以從Java中調用。

http://en.wikipedia.org/wiki/Gluegen

爲了得到一個頭文件的wininet.dll文件,你可能需要有平臺SDK(或Windows SDK,最新版本)。您還可以在網上搜索包含此頭文件的聯機存儲庫。

GlueGen需要一個頭文件,一個ANSI C編譯器等

還有一個不太爲人所知的庫調用NativeCall,不需要GlueGen。它已經有兼容Java的二進制文件。這顯然比較慢,因爲它會根據Java的請求動態加載DLL。我沒有使用過這一點,但是,但是聽起來前途:

http://johannburkard.de/software/nativecall/

12

我不得不這樣做一會兒前。你需要一個C編譯器和Windows頭文件。我使用了mingw,因爲它是免費的,我只編譯一個小文件。

首先你要上你的課。這裏有一個例子:

package org.whatever.thingy; 

public class MyClass { 
    // Here is a JNI method, identified by 'native' 

    public static native callWin32Thingy(int x, int y, boolean z); 

    /* At this point, normal class stuff, other methods, variables, whatever */ 
} 

你然後用自帶的JDK中的命令,它會自動把你的類,並生成h和.c文件之一。該命令是「javah」。方法簽名將如下所示:

JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy 
    (JNIEnv *, jclass, jint, jint, jboolean); 

在.c文件中,可以包含任何需要的窗口標頭,並充實該方法。

JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy 
    (JNIEnv *a, jclass b, jint c, jint d, jboolean e) { 
    // Prep steps.... 

    Win32MethodCallWeCareAbout(x, y, z, hWhatever); 

    // Cleanup stuff... 
} 

這是非常重要不重命名的方法,這就是它被如何與您的特定類關聯。

一旦你得到了,你將這些文件編譯成一個DLL。這裏是我用於mingw的命令,你必須調整類/路徑/等。

c:/MinGW/bin/gcc -c -Ic:/MinGW/include -I"c:/Program Files/Java/jdk1.5.0_12/include" 
    -I"c:/Program Files/Java/jdk1.5.0_12/include/win32" -D__int64="long long" 
    com_whatever_thingy_MyClass_JNIHelper.c 

c:/MinGW/bin/gcc -shared -o JNIHelper.dll 
    com_whatever_thingy_MyClass_JNIHelper_JNIHelper.o 
    -Wl,--add-stdcall-alias,--kill-at,--output-def,def_file 

這將產生一些文件,包括JNIHelper.dll,這就是我命名我的DL​​L。

在這一點上,你基本上完成了。您正常使用Java類,並在調用靜態方法時運行Win32代碼。你所要做的就是導入庫。某處在你的代碼(我把它放在一個靜態塊在我的課),你需要這條線:

System.loadLibrary("JNIHelper"); 

這將導致Java來加載一個名爲「JNIHelper.dll」庫,並將其鏈接到代碼。它必須位於Java知道的圖書館路徑的某個地方。

就是這樣。這是一堆樣板,但如果你正在做一些簡單的包裝,很容易。如果你不得不處理Java類型或分配內存,情況會變得更糟(注意:我沒有,所以我沒有經驗)。

有一個完整的教程here(第一,我發現今天看起來體面的,你可以在網絡上找到他人。在Wikipedia文章JNI有更多的信息了。

希望這有助於。

+1

你不需要Java類中的「native」關鍵字嗎? – 2010-03-06 12:24:11

+0

@Thorbjørn:你的權利,我錯過了,謝謝。編輯添加。 – MBCook 2010-03-06 19:37:36