如何在Java程序中调用DLL中的方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25454697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to call a method in DLL in a Java program
提问by Vivek
I am trying to call a method in a DLL using JNA. So far have loaded the DLL using
我正在尝试使用 JNA 调用 DLL 中的方法。到目前为止已经加载了 DLL 使用
Runtime.getRuntime().load("myworkspace/test.dll");
This dll contaings a method that I need to access. How can I execute the method present in DLL in my Java file. Do I create an object or something of the DLL and then get the method name after the dot operator.
这个 dll 包含一个我需要访问的方法。如何在我的 Java 文件中执行 DLL 中存在的方法。我是否创建了一个对象或 DLL 的某些内容,然后在点运算符之后获取方法名称。
回答by Rahul Tripathi
From the source:
从来源:
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 ##代码## 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);
}
}
回答by Alter Reisbrei
Loading the DLL is only the easiest step.
加载 DLL 只是最简单的步骤。
As it is not really trivial to call a method of a DLL from Java this answer is only a summary of hints what you have to do to call a function from a DLL. The whole story would fill a book. And in fact there are several books about JNI (Java Native Interface).
由于从 Java 调用 DLL 的方法并不是很简单,因此这个答案只是提示从 DLL 调用函数必须执行的操作的摘要。整个故事将填满一本书。事实上,有几本关于 JNI(Java Native Interface)的书。
To call a function in a native library you have to declare a method in your java class as native with the java keyword native
. The declaration of this method must not have a body.
要调用本地库中的函数,您必须使用 java 关键字将 java 类中的方法声明为本地方法native
。此方法的声明不能有主体。
The name of the function exported from your DLL must match the following pattern:
Java_classname_methodname
where classname
is the name of the class where you declared the native method methodname
.
从您的 DLL 导出的函数名称必须与以下模式匹配:
Java_classname_methodname
其中classname
是您声明本机方法的类的名称methodname
。
For example if you declare a native method private native void sayHello()
in your class MyClass the name of the DLL's function would be: Java_MyClass_sayHello
例如,如果您private native void sayHello()
在类 MyClass 中声明本机方法,则 DLL 函数的名称将是:Java_MyClass_sayHello
Also keep in mind that the function must be exported from the DLL with the correct calling conventions JNIEXPORT and JNICALL which are defined in the header file jni.h that comes with your JDK (see include folder)
还要记住,必须使用正确的调用约定 JNIEXPORT 和 JNICALL 从 DLL 导出函数,这些约定在 JDK 附带的头文件 jni.h 中定义(请参阅包含文件夹)
Every function of a DLL to be called from Java also must have two "hidden" arguments as first parameters (JNIEnv *env, jobject obj)
.
env
is a pointer to the calling JVM which allows you callback into the JVM and obj
is the object from which the method was called.
要从 Java 调用的 DLL 的每个函数也必须有两个“隐藏”参数作为第一个参数(JNIEnv *env, jobject obj)
。
env
是指向调用 JVM 的指针,它允许您回调到 JVM,并且obj
是调用方法的对象。
So the whole definition of the DLL's method in our example would be:
JNIEXPORT void JNICALL Java_MyClass_sayHello(JNIEnv *, jobject);
因此,在我们的示例中,DLL 方法的整个定义将是:
JNIEXPORT void JNICALL Java_MyClass_sayHello(JNIEnv *, jobject);
Due to these restrictions of JNI a DLL called from your code must be specifially made for your code. To use an arbitrary DLL from Java you usually have to create an adapting DLL with the conventions of JNI that itself loads the "target" DLL and calls the required functions.
由于 JNI 的这些限制,必须为您的代码专门制作从您的代码调用的 DLL。要使用 Java 中的任意 DLL,您通常必须使用 JNI 的约定创建一个自适应 DLL,该 DLL 本身会加载“目标”DLL 并调用所需的函数。
To generate the correct headers for your adapter DLL you can use the tool javah shipped with the JDK. This tool will generate the headers to be implemented from your Java code.
要为您的适配器 DLL 生成正确的头文件,您可以使用 JDK 附带的工具 javah。此工具将生成要从您的 Java 代码实现的标头。
For further information the documentation of JNI will cover all questions about interaction with the JVM from native code. http://docs.oracle.com/javase/7/docs/technotes/guides/jni/
有关更多信息,JNI 文档将涵盖有关从本机代码与 JVM 交互的所有问题。http://docs.oracle.com/javase/7/docs/technotes/guides/jni/