java - 使用JNI调用给定DLL文件中定义的函数

标签 java eclipse visual-studio dll java-native-interface

我的目标是使用JNI从kernel32.dll访问功能。正如您在下面看到的,我做得很糟糕。我在答案中写下了整个过程。

Kernel32.java:

package tn.kernel;

public final class Kernel32 {
    public static boolean loadKernel32(){
        System.loadLibrary("kernel32");
        return true;
    }

    public static native boolean K32EnumProcesses(int[] pProcessIds, int cb, int[] pBytesReturned);
}


MainClass.java:

package tn.kernel;

public class MainClass {

    public static void main(String[] args) {
        System.out.println("Program started.");

        if(Kernel32.loadKernel32())
            System.out.println("Kernel32.dll loaded.");

        int n = 2000;
        int[] procs = new int[n];
        int ls = Integer.SIZE;
        int[] rs = new int[1];

        if(Kernel32.K32EnumProcesses(procs, ls * n, rs)){
            System.out.println("Success");
        }

        System.out.println("Done.");
    }

}


输出:

Program started.
Kernel32.dll loaded.
Exception in thread "main" java.lang.UnsatisfiedLinkError: tn.kernel.Kernel32.K32EnumProcesses([II[I)Z
    at tn.kernel.Kernel32.K32EnumProcesses(Native Method)
    at tn.kernel.MainClass.main(MainClass.java:15)


这是EnumProcesses的语法:

BOOL WINAPI EnumProcesses(
  _Out_ DWORD *pProcessIds,
  _In_  DWORD cb,
  _Out_ DWORD *pBytesReturned
);


如果PSAPI_VERSION为2或更大,则此函数在Psapi.h中定义为K32EnumProcesses,并在Kernel32.lib和Kernel32.dll中导出。如果PSAPI_VERSION为1,则此函数在Psapi.h中定义为EnumProcesses,并在Psapi.lib和Psapi.dll中作为调用K32EnumProcesses的包装程序导出。资料来源:msnd.microsoft.com

我尝试使用K32EnumProcesses和EnumProcesses。结果相同。

最佳答案

为Windows创建一个64位的动态链接库

先决条件:Visual Studio

1 /创建一个Visual Studio C ++项目(例如:dllexample)

•选择“ Win32 Consol应用程序”


选择“ DLL”
选择“空项目”


2 /在“解决方案资源管理器”中,右键单击“头文件”>“添加”>“新建项…”>选择一个名称(例如:dllexample.h)>“添加”

•通过以下方式在“ dllexample.h”中定义函数的标题:

__declspec(dllexport) <type> funcName(parameters…);
…


3 /在“解决方案资源管理器”中,右键单击“源文件”>“添加”>“新建项…”>选择一个名称(例如:dllexample.cpp)>“添加”

• 采用:

#include “dllexample.h”


•在“ dllexample.cpp”源文件中定义函数的主体(来自“ dllexample.h”头文件):

<type> funcName(parameters…){
    //body instructions
}


•在上方工具栏中,选择“ x64”

•选择“构建”>“构建解决方案”

4 /完成

•您可以在“ projects / dllexample / x64 / Debug”中找到“ dllexample.dll”和“ dllexample.lib”

•您可以在“ projects / dllexample / dllexample”中找到“ dllexample.h”


从Windows上的另一个64位DLL或可执行文件调用64位DLL文件(例如:dllexample.dll)

先决条件:“ dllexample.dll”,“ dllexample.lib”和“ dllexample.h”或精确的功能描述或指南以及Visual Studio

1 /创建一个Visual Studio C ++项目(例如:dllcall)

•选择“ Win32 Consol应用程序”


选择“ DLL”创建一个DLL文件,选择“ Consol Application”创建一个可执行文件
选择“空项目”


2 /将“ dllexample.dll”,“ dllexample.lib”和“ dllexample.h”复制到“ projects / dllcall / dllcall”

3 /在“解决方案资源管理器”中,右键单击“头文件”>“添加”>“现有项…”>选择“ dllexample.h”>“添加”

•如果要制作DLL文件,请创建一个新的头文件(例如:dllcall.h),在其中您可以通过以下方式定义函数的头:

__declspec(dllexport) <type> funcName(parameters…);
…


4 /在“解决方案资源管理器”中,右键单击“源文件”>“添加”>“新建项…”>选择一个名称(例如:dllcall.cpp)>“添加”

• 采用:

#include “dllexample.h”


•如果要创建DLL文件,请使用:

#include “dllcall.h”


然后在“ dllcall.cpp”源文件中定义函数的主体(来自“ dllcall.h”头文件)。同时,您可以从“ dllexample.h”调用函数:

<type> funcName(parameters…){
    //body instructions
}


•在上方工具栏中,选择“ x64”

•在“解决方案资源管理器”中,右键单击“ dllcall”>“属性”>“链接器”>“输入”>“其他依赖项”>“编辑”>添加“ dllexample.lib”(此选项仅针对当前Visual Studio项目的x64调试器)

•选择“构建”>“构建解决方案”以生成DLL和导入库(.lib)文件,选择“运行”以生成可执行文件并对其进行测试

5 /完成

•您可以在“ projects / dllcall / x64 / Debug”中找到“ dllcall.dll”和“ dllcall.lib”或“ dllcall.exe”

•您可以在“ projects / dllcall / dllcall”中找到“ dllcall.h”

通过JNI从64位Java程序调用64位DLL文件(例如:dllexample.dll)

先决条件:“ dllexample.dll”,“ dllexample.lib”和“ dllexample.h”或精确的功能描述或指南。 Visual Studio,带有JNI插件的Eclipse

1 /创建一个Eclipse Java项目(例如:dlltest)

2 /创建一个类(例如:my.package.JNIClass)

•使用关键字在“ dllexample.h”中的函数定义附近定义方法标头:

public static final native <type> funcName(parameters..);
…


•运行项目以生成“ JNIClass.class”

3 /在“ workspace / dllcall / src”文件夹中打开命令行

•通过运行以下命令生成“ my_package_JNIClass.h”头文件:

javah my.package.JNIClass


4 /创建一个64位DLL文件(例如:dllcall.dll),该文件调用“ dllexample.dll”并包含“ my_package_JNIClass.h”

•在“ dllcall.cpp”源文件中,定义在“ my_package_JNIClass.h”头文件中定义的函数体

•“ my_package_JNIClass.h”包括“ jni.h”,要使其运行,必须转到Visual Studio中的“ Solution Explorer”,然后右键单击“ Properties”>“ Configuration Properties”>“ C / C ++”>“常规”>“其他包含目录”>添加64位“ java / include”和“ java / include / win32”路径(此选项仅为当前Visual Studio项目的x64调试器设置)

5 /将“ dllcall.dll”和“ dllexample.dll”复制到“ workspace / dllcall / src”

•在“ Package Explorer”中,右键单击“ dlltest”>“ Properties”>“ Java Build Path”>“ Source”>展开“ my / package / src”>选择“ Native Library Location”>“ Edit”>添加“ my / package / src”作为位置路径

•使用以下命令将DLL文件导入“ JNIClass.java”中:

static {
    System.loadLibrary(“dllexample”);
    System.loadLibrary(“dllcall”);
}


6 /如果未选择64位JRE,则转到“运行”>“运行配置”>“ JRE”>“备用JRE”>“已安装JRE”>放入64位Java JDK目录(应该是这样的: “ C:\ Program Files \ Java \ jdk”,而在“ Program Files(x86)”文件夹中可以找到32位Java JDK

7 /完成

•现在,您可以使用在步骤2中定义的方法

关于java - 使用JNI调用给定DLL文件中定义的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44926904/

相关文章:

java - 在 Google App Engine 上建立 TLS v1.2 连接

Java XPath API 提取选择性文本

linux - Eclipse Helios 无法加载玩具插件

Eclipse 火星紧凑型用户界面

visual-studio - 在 Visual Studio 中粘贴到 .h 文件时保留空格

c++ - Visual C++ TODO 任务列表不显示元素

java - 转换为 JScrollPane 中 JTable 的图像

java - 仅更改 Eclipse 待办事项的颜色 - 而不是整个评论

eclipse - Eclipse STS Grails路径问题

c# - 尝试更改目标框架时从 Visual Studio 收到拒绝访问错误