作為使用J/Direct唯一的途徑,@dll.import引導命令相當靈活。它提供了為數眾多的修改符,可用它們自定義同非Java代碼建立鏈接關系的方式。它亦可應用於類內的一些方法,或應用於整個類。也就是說,我們在那個類內聲明的所有方法都是在相同的DLL裡實現的。下面讓我們具體研究一下這些特性。
1. 別名處理和按順序鏈接
為了使@dll.import引導命令能象上面顯示的那樣工作,DLL內的函數必須按名字導出。然而,我們有時想使用與DLL裡原始名字不同的一個名字(別名處理),否則函數就可能按編號(比如按順序)導出,而不是按名字導出。下面這個例子聲明了FinestraDiMessaggio()(用意大利語說的“MessageBox”)。正如大家看到的那樣,使用的語法是非常簡單的。
public class Aliasing { public static void main(String args[]) throws UnsatisfiedLinkError { FinestraDiMessaggio(0, "Created by the MessageBox() Win32 func", "Thinking in Java", 0); } /** @dll.import("USER32", entrypoint="MessageBox") */ private static native int FinestraDiMessaggio(int hwndOwner, String text, String title, int fuStyle); }
下面這個例子展示了如何同DLL裡並非按名字導出的一個函數建立鏈接,那個函數事實是按它們在DLL裡的位置導出的。這個例子假設有一個名為MYMATH的DLL,這個DLL在位置編號3處包含了一個函數。那個函數獲取兩個整數作為自變量,並返回兩個整數的和。
public class ByOrdinal { public static void main(String args[]) throws UnsatisfiedLinkError { int j=3, k=9; System.out.println("Result of DLL function:" + Add(j,k)); } /** @dll.import("MYMATH", entrypoint = "#3") */ private static native int Add(int op1,int op2); }
可以看出,唯一的差異就是entrypoint自變量的形式。
2. 將@dll.import應用於整個類
@dll.import引導命令可應用於整個類。也就是說,那個類的所有方法都是在相同的DLL裡實現的,並具有相同的鏈接屬性。引導命令不會由子類繼承;考慮到這個原因,而且由於DLL裡的函數是自然的static函數,所以更佳的設計方案是將API函數封裝到一個獨立的類裡,如下所示:
/** @dll.import("USER32") */ class MyUser32Access { public static native int MessageBox(int hwndOwner, String text, String title, int fuStyle); public native static boolean MessageBeep(int uType); } public class WholeClass { public static void main(String args[]) throws UnsatisfiedLinkError { MyUser32Access.MessageBeep(4); MyUser32Access.MessageBox(0, "Created by the MessageBox() Win32 func", "Thinking in Java", 0); } }
由於MessageBeep()和MessageBox()函數已在不同的類裡被聲明成static函數,所以必須在調用它們時規定作用域。大家也許認為必須用上述的方法將所有Win32 API(函數、常數和數據類型)都映射成Java類。但幸運的是,根本不必這樣做。