J/Direct是調用Win32 DLL函數最簡單的方式。它的主要設計目標是與Win32API打交道,但完全可用它調用其他任何API。但是,盡管這一特性非常方便,但它同時也造成了某些限制,且降低了性能(與RNI相比)。但J/Direct也有一些明顯的優點。首先,除希望調用的那個DLL裡的代碼之外,沒有必要再編寫額外的非Java代碼,換言之,我們不需要一個封裝器或者代理/存根DLL。其次,函數自變量與標准數據類型之間實現了自動轉換。若必須傳遞用戶自定義的數據類型,那麼J/Direct可能不按我們的希望工作。第三,就象下例展示的那樣,它非常簡單和直接。只需少數幾行,這個例子便能調用Win32 API函數MessageBox(),它能彈出一個小的模態窗口,並帶有一個標題、一條消息、一個可選的圖標以及幾個按鈕。
public class ShowMsgBox { public static void main(String args[]) throws UnsatisfiedLinkError { MessageBox(0, "Created by the MessageBox() Win32 func", "Thinking in Java", 0); } /** @dll.import("USER32") */ private static native int MessageBox(int hwndOwner, String text, String title, int fuStyle); }
令人震驚的是,這裡便是我們利用J/Direct調用Win32 DLL函數所需的全部代碼。其中的關鍵是位於示范代碼底部的MessageBox()聲明之前的@dll.import引導命令。它表面上看是一條注釋,但實際並非如此。它的作用是告訴編譯器:引導命令下面的函數是在USER32 DLL裡實現的,而且應相應地調用。我們要做的全部事情就是提供與DLL內實現的函數相符的一個原型,並調用函數。但是毋需在Java版本裡手工鍵入需要的每一個Win32 API函數,一個Microsoft Java包會幫我們做這件事情(很快就會詳細解釋)。為了讓這個例子正常工作,函數必須“按名稱”由DLL導出。但是,也可以用@dll.import引導命令“按順序”鏈接。舉個例子來說,我們可指定函數在DLL裡的入口位置。稍後還會具體講述@dll.import引導命令的特性。
用非Java代碼進行鏈接的一個重要問題就是函數參數的自動配置。正如大家看到的那樣,MessageBox()的Java聲明采用了兩個字串自變量,但原來的C方案則采用了兩個char指針。編譯器會幫助我們自動轉換標准數據類型,同時遵照本章後一節要講述的規則。
最好,大家或許已注意到了main()聲明中的UnsatisfiedLinkError異常。在運行期的時候,一旦鏈接程序不能從非Java函數裡解析出符號,就會觸發這一異常(事件)。這可能是由多方面的原因造成的:.dll文件未找到;不是一個有效的DLL;或者J/Direct未獲您所使用的虛擬機的支持。為了使DLL能被找到,它必須位於Windows或Windows\System目錄下,位於由PATH環境變量列出的一個目錄中,或者位於和.class文件相同的目錄。J/Direct獲得了Microsoft Java編譯器1.02.4213版本及更高版本的支持,也獲得了Microsoft JVM 4.79.2164及更高版本的支持。為了解自己編譯器的版本號,請在命令行下運行JVC,不要加任何參數。為了解JVM的版本號,請找到msjava.dll的圖標,並利用右鍵彈出菜單觀察它的屬性。