如何在Java程序中调用DLL中的方法

我试图使用JNA调用DLL中的方法。 到目前为止已经加载了DLL

Runtime.getRuntime().load("myworkspace/test.dll"); 

这个dll包含了我需要访问的方法。 如何在Java文件中执行DLL中的方法。 我是否创建一个对象或DLL的某些东西,然后在点运算符后获取方法名称。

从来源 :

 package jnahelloworldtest; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.Platform; import com.sun.jna.*; /** Simple example of native library declaration and usage. */ public class Main { public interface simpleDLL extends Library { simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary( (Platform.isWindows() ? "simpleDLL" : "simpleDLLLinuxPort"), simpleDLL.class); // it's possible to check the platform on which program runs, for example purposes we assume that there's a linux port of the library (it's not attached to the downloadable project) byte giveVoidPtrGetChar(Pointer param); // char giveVoidPtrGetChar(void* param); int giveVoidPtrGetInt(Pointer param); //int giveVoidPtrGetInt(void* param); int giveIntGetInt(int a); // int giveIntGetInt(int a); void simpleCall(); // void simpleCall(); } public static void main(String[] args) { simpleDLL sdll = simpleDLL.INSTANCE; sdll.simpleCall(); // call of void function int a = 3; int result1 = sdll.giveIntGetInt(a); // calling function with int parameter&result System.out.println("giveIntGetInt("+a+"): " + result1); String testStr = "ToBeOrNotToBe"; Memory mTest = new Memory(testStr.length()+1); // '+1' remember about extra byte for \0 character! mTest.setString(0, testStr); String testReturn = mTest.getString(0); // you can see that String got properly stored in Memory object System.out.println("String in Memory:"+testReturn); Memory intMem = new Memory(4); // allocating space intMem.setInt(0, 666); // setting allocated memory to an integer Pointer intPointer = intMem.getPointer(0); int int1 = sdll.giveVoidPtrGetInt(Pointer.NULL); // passing null, getting default result System.out.println("giveVoidPtrGetInt(null):" + int1); int int2 = sdll.giveVoidPtrGetInt(intMem); // passing int stored in Memory object, getting it back //int int2 = sdll.giveVoidPtrGetInt(intPointer); causes JVM crash, use memory object directly! System.out.println("giveVoidPtrGetInt(666):" + int2); byte char1 = sdll.giveVoidPtrGetChar(Pointer.NULL); // passing null, getting default result byte char2 = sdll.giveVoidPtrGetChar(mTest); // passing string stored in Memory object, getting first letter System.out.println("giveVoidPtrGetChar(null):" + (char)char1); System.out.println("giveVoidPtrGetChar('ToBeOrNotToBe'):" + (char)char2); } } 

加载DLL只是最简单的步骤。

因为从Java调用DLL的方法并不是真的很简单,所以这个答案只是提示从DLL调用函数时必须做的事情。 整个故事将填补一本书。 实际上有几本关于JNI(Java Native Interface)的书籍。

要在本机库中调用函数,必须使用java关键字native将java类中的方法声明为native 。 此方法的声明不得有正文。

从DLL导出的函数的名称必须与以下模式匹配: Java_classname_methodname其中classname是您声明本机方法Java_classname_methodname classname的名称。

例如,如果在类MyClass中声明本机方法private native void sayHello() ,则DLL函数的名称将为: Java_MyClass_sayHello

还要记住,必须使用正确的调用约定JNIEXPORT和JNICALL从DLL导出函数,这些约定在JDK附带的头文件jni.h中定义(请参阅include文件夹)

要从Java调用的DLL的每个函数也必须有两个“隐藏”参数作为第一个参数(JNIEnv *env, jobject obj)env是一个指向调用JVM的指针,它允许你回调到JVM中,而obj是调用该方法的对象。

所以我们的例子中DLL方法的整个定义是: JNIEXPORT void JNICALL Java_MyClass_sayHello(JNIEnv *, jobject);

由于JNI的这些限制,必须专门为您的代码调用从您的代码调用的DLL。 要使用Java中的任意DLL,您通常必须使用JNI的约定创建一个自适应DLL,JNI本身会加载“目标”DLL并调用所需的函数。

要为适配器DLL生成正确的标头,可以使用JDK附带的工具javah。 此工具将生成要从Java代码实现的标头。

有关更多信息,JNI的文档将涵盖有关从本机代码与JVM交互的所有问题。 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/