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

Viv*_*vek 29 java dll java-native-interface jna

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

Runtime.getRuntime().load("myworkspace/test.dll");
Run Code Online (Sandbox Code Playgroud)

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

Rah*_*thi 26

来源:

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);

    }
}
Run Code Online (Sandbox Code Playgroud)


小智 12

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

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

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

从DLL导出的函数的名称必须与以下模式匹配: Java_classname_methodnamewhere classname是您声明本机方法的类的名称methodname.

例如,如果private native void sayHello()在类MyClass中声明本机方法,则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,它本身加载"目标"DLL并调用所需的函数.

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

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

  • 问题是关于JNA.(JNA使用JNI.) (2认同)
  • 是否有一个用于在 java 中处理 dll 的 api - 例如,您可以循环遍历所有可能的命令(方法)以查看 dll 包含的内容? (2认同)