简体   繁体   English

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

[英]Using JNI to call functions defined within a given DLL file

My objective was to use JNI to access functions from kernel32.dll. 我的目标是使用JNI从kernel32.dll访问功能。 As you can see below, I was doing pretty bad. 正如您在下面看到的,我做得很糟糕。 I wrote down the whole procedure in the answer. 我在答案中写下了整个过程。

Kernel32.java : 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 : 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.");
    }

}

OUTPUT : 输出:

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)

This the syntax for EnumProcesses : 这是EnumProcesses的语法:

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

If PSAPI_VERSION is 2 or greater, this function is defined as K32EnumProcesses in Psapi.h and exported in Kernel32.lib and Kernel32.dll. 如果PSAPI_VERSION为2或更大,则此函数在Psapi.h中定义为K32EnumProcesses ,并在Kernel32.lib和Kernel32.dll中导出。 If PSAPI_VERSION is 1, this function is defined as EnumProcesses in Psapi.h and exported in Psapi.lib and Psapi.dll as a wrapper that calls K32EnumProcesses . 如果PSAPI_VERSION为1,则此函数在Psapi.h中定义为EnumProcesses ,并在Psapi.lib和Psapi.dll中作为调用K32EnumProcesses的包装器导出 Source : msnd.microsoft.com 资料来源: msnd.microsoft.com

I tried with both K32EnumProcesses and EnumProcesses. 我尝试使用K32EnumProcesses和EnumProcesses。 Same results. 结果相同。

Creating a 64 bits Dynamic-Link Library for Windows 为Windows创建64位动态链接库

Prerequisites: Visual Studio 先决条件:Visual Studio

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

• Select “Win32 Consol Application” •选择“ Win32 Consol应用程序”

  • Select “DLL” 选择“ DLL”
  • Select “Empty project” 选择“空项目”

2/ In “Solution explorer” right-click on “Header Files” > “Add” > “New Item…” > choose a name (ex: dllexample.h) > “Add” 2 /在“解决方案资源管理器”中,右键单击“头文件”>“添加”>“新项目…”>选择一个名称(例如:dllexample.h)>“添加”

• Define the headers of your functions in “dllexample.h” this way: •通过以下方式在“ dllexample.h”中定义函数的标题:

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

3/ In “Solution explorer” right-click on “Source Files” > “Add” > “New Item…” > choose a name (ex: dllexample.cpp) > “Add” 3 /在“解决方案资源管理器”中,右键单击“源文件”>“添加”>“新建项…”>选择一个名称(例如:dllexample.cpp)>“添加”

• Use: • 采用:

#include “dllexample.h”

• Define the body of your functions (from the “dllexample.h” header file) in the “dllexample.cpp” source file: •在“ dllexample.cpp”源文件中定义函数的主体(来自“ dllexample.h”头文件):

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

• In the upper toolbar select “x64” •在上方工具栏中,选择“ x64”

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

4/ Done 4 /完成

• You can find “dllexample.dll” and “dllexample.lib” in “projects/dllexample/x64/Debug” •您可以在“ projects / dllexample / x64 / Debug”中找到“ dllexample.dll”和“ dllexample.lib”

• You can find “dllexample.h” in “projects/dllexample/dllexample” •您可以在“ projects / dllexample / dllexample”中找到“ dllexample.h”

Calling a 64 bits DLL file (ex: dllexample.dll) from another 64 bits DLL or executable file on Windows 从Windows上的另一个64位DLL或可执行文件调用64位DLL文件(例如:dllexample.dll)

Prerequisites: “dllexample.dll”, “dllexample.lib” and “dllexample.h” or a precise functions description or guide and Visual Studio 先决条件:“ dllexample.dll”,“ dllexample.lib”和“ dllexample.h”或精确的功能描述或指南以及Visual Studio

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

• Select “Win32 Consol Application” •选择“ Win32 Consol应用程序”

  • Select “DLL” to create a DLL file, “Consol Application” to create an executable file 选择“ DLL”创建一个DLL文件,选择“ Consol Application”创建一个可执行文件
  • Select “Empty project” 选择“空项目”

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

3/ In “Solution explorer” right-click on “Header Files” > “Add” > “Existing Item…” > select ”dllexample.h” > “Add” 3 /在“解决方案资源管理器”中,右键单击“头文件”>“添加”>“现有项...”>选择“ dllexample.h”>“添加”

• If you're making a DLL file, create a new header file (ex: dllcall.h) in which you define the headers of your functions this way: •如果要创建DLL文件,请创建一个新的头文件(例如:dllcall.h),在其中您可以通过以下方式定义函数的头:

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

4/ In “Solution explorer” right-click on “Source Files” > “Add” > “New Item…” > choose a name (ex: dllcall.cpp) > “Add” 4 /在“解决方案资源管理器”中,右键单击“源文件”>“添加”>“新建项…”>选择一个名称(例如:dllcall.cpp)>“添加”

• Use: • 采用:

#include “dllexample.h”

• If you're creating a DLL file, use: •如果要创建DLL文件,请使用:

#include “dllcall.h”

And then define the body of the functions (from the “dllcall.h” header file) in the “dllcall.cpp” source file. 然后在“ dllcall.cpp”源文件中定义函数的主体(来自“ dllcall.h”头文件)。 At the same time you can call functions from “dllexample.h”: 同时,您可以从“ dllexample.h”调用函数:

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

• In the upper toolbar select “x64” •在上方工具栏中,选择“ x64”

• In “Solution explorer”, right-click on “dllcall” > “Properties” > “Linker” > “Input” > “Additional Dependencies” > “Edit” > add “dllexample.lib” (this option will be set only for the x64 debugger of the current Visual Studio project) •在“解决方案资源管理器”中,右键单击“ dllcall”>“属性”>“链接器”>“输入”>“其他依赖项”>“编辑”>添加“ dllexample.lib”(此选项仅针对当前Visual Studio项目的x64调试器)

• Select “Build” > “Build Solution” to generate the DLL and the Import Library (.lib) files, “Run” to generate the executable file and test it •选择“构建”>“构建解决方案”以生成DLL和导入库(.lib)文件,选择“运行”以生成可执行文件并对其进行测试

5/ Done 5 /完成

• You can find “dllcall.dll” and “dllcall.lib” or “dllcall.exe” in “projects/dllcall/x64/Debug” •您可以在“ projects / dllcall / x64 / Debug”中找到“ dllcall.dll”和“ dllcall.lib”或“ dllcall.exe”

• You can find “dllcall.h” in “projects/dllcall/dllcall” •您可以在“ projects / dllcall / dllcall”中找到“ dllcall.h”

Calling a 64 bits DLL file (ex: dllexample.dll) from a 64 bits Java program through JNI 通过JNI从64位Java程序调用64位DLL文件(例如:dllexample.dll)

Prerequisites: “dllexample.dll”, “dllexample.lib” and “dllexample.h” or a precise functions description or guide. 先决条件:“ dllexample.dll”,“ dllexample.lib”和“ dllexample.h”或精确的功能描述或指南。 Visual Studio, Eclipse with JNI plugin Visual Studio,带有JNI插件的Eclipse

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

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

• Define methods headers as close as the functions definitions in “dllexample.h” using keywords: •使用关键字在“ dllexample.h”中的函数定义附近定义方法标头:

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

• Run the project to generate “JNIClass.class” •运行项目以生成“ JNIClass.class”

3/ Open Command Line in folder “workspace/dllcall/src” 3 /在“ workspace / dllcall / src”文件夹中打开命令行

• Generate “my_package_JNIClass.h” header file by running command: •通过运行以下命令生成“ my_package_JNIClass.h”头文件:

javah my.package.JNIClass

4/ Create a 64 bits DLL file (ex: dllcall.dll) that calls “dllexample.dll” and includes “my_package_JNIClass.h” 4 /创建一个64位DLL文件(例如:dllcall.dll),该文件调用“ dllexample.dll”并包含“ my_package_JNIClass.h”

• In the “dllcall.cpp” source file, define the bodies of functions that are defined in the “my_package_JNIClass.h” header file •在“ dllcall.cpp”源文件中,定义“ my_package_JNIClass.h”头文件中定义的函数主体

• “my_package_JNIClass.h” includes “jni.h”, to make it work, you must go to “Solution explorer” in Visual Studio and right-click on “Properties” > “Configuration Properties” > “C/C++” > “General” > “Additional Include Directories” > add the 64 bits “java/include” and “java/include/win32” paths (this option will be set only for the x64 debugger of the current Visual Studio project) •“ 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/ Copy “dllcall.dll” and “dllexample.dll” to “workspace/dllcall/src” 5 /将“ dllcall.dll”和“ dllexample.dll”复制到“ workspace / dllcall / src”

• In “Package explorer”, right-click on “dlltest” > “Properties” > “Java Build Path” > “Source” > expand “my/package/src” > select “Native Library Location” > “Edit” > add “my/package/src” as location path •在“ Package Explorer”中,右键单击“ dlltest”>“ Properties”>“ Java Build Path”>“ Source”>展开“ my / package / src”>选择“ Native Library Location”>“ Edit”>添加“ my / package / src”作为位置路径

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

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

6/ If the 64 bits JRE is not selected, then go to “Run” > “Run Configurations” > “JRE” > “Alternate JREs” > “Installed JREs” > put the 64 bits Java JDK directory (Should be something like: “C:\\Program Files\\Java \\jdk”, while 32 bits Java JDK can be found in the “Program Files (x86)” folder 6 /如果未选择64位JRE,则转至“运行”>“运行配置”>“ JRE”>“备用JRE”>“已安装JRE”>放入64位Java JDK目录(应类似: “ C:\\ Program Files \\ Java \\ jdk”,而在“ Program Files(x86)”文件夹中可以找到32位Java JDK

7/ Done 7 /完成

• Now you can use the methods you defined in step 2 •现在,您可以使用在步骤2中定义的方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM