Java 使用JNI调用给定DLL文件中定义的函数
我的目标是使用JNI从kernel32.dll访问函数。正如你在下面看到的,我做得很糟糕。我在答案中写下了整个过程 Kernel32.java:Java 使用JNI调用给定DLL文件中定义的函数,java,eclipse,visual-studio,dll,java-native-interface,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
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);
}
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.");
}
}
MainClass.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);
}
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)
以下是枚举进程的语法:
BOOL WINAPI EnumProcesses(
_Out_ DWORD *pProcessIds,
_In_ DWORD cb,
_Out_ DWORD *pBytesReturned
);
如果PSAPI_版本为2或更高,则此函数在PSAPI.h中定义为K32EnumProcesses,并在Kernel32.lib和Kernel32.dll中导出。如果PSAPI_VERSION为1,则此函数在PSAPI.h中定义为EnumProcesses,并在PSAPI.lib和PSAPI.dll中导出为调用K32EnumProcesses的包装器。来源:msnd.microsoft.com
我尝试了K32EnumProcess和EnumProcess。相同的结果。为Windows创建64位动态链接库
先决条件:Visual Studio
1创建VisualStudioC++项目(EX:DLLIVE)
•选择“Win32控制台应用程序”- 选择“DLL”
- 选择“空项目”
__declspec(dllexport) <type> funcName(parameters…);
…
__declspec(dllexport) <type> funcName(parameters…);
…
•在“dllexample.cpp”源文件中定义函数体(从“dllexample.h”头文件):
<type> funcName(parameters…){
//body instructions
}
•如果要创建DLL文件,请使用:
#include “dllcall.h”
然后在“dllcall.cpp”源文件中定义函数体(来自“dllcall.h”头文件)。同时,您可以从“dllexample.h”调用函数:
<type> funcName(parameters…){
//body instructions
}
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中的“解决方案资源管理器”,右键单击“属性”>“配置属性”>“C/C++”>“常规”>“其他包含目录”>添加64位“java/Include”和“java/Include/win32”路径(此选项将仅为当前Visual Studio项目的x64调试器设置)
5/将“dllcall.dll”和“dllexample.dll”复制到“workspace/dllcall/src”
•在“包资源管理器”中,右键单击“dlltest”>“属性”>“Java构建路径”>“源”>展开“my/Package/src”>选择“本机库位置”>“编辑”>添加“my/Package/src”作为位置路径
•使用以下方法导入“JNIClass.java”中的DLL文件:
static {
System.loadLibrary(“dllexample”);
System.loadLibrary(“dllcall”);
}
6/如果未选择64位JRE,则转到“运行”>“运行配置”>“JRE”>“备用JRE”>“已安装JRE”>放置64位Java JDK目录(应该类似于:“C:\Program Files\Java\JDK”,而32位Java JDK可以在“Program Files(x86)”文件夹中找到
7/完成
•现在,您可以使用步骤2中定义的方法为Windows创建64位动态链接库
先决条件:Visual Studio
1创建VisualStudioC++项目(EX:DLLIVE)
•选择“Win32控制台应用程序”- 选择“DLL”
- 选择“空项目”
__declspec(dllexport) <type> funcName(parameters…);
…
__declspec(dllexport) <type> funcName(parameters…);
…
•在“dllexample.cpp”源文件中定义函数体(从“dllexample.h”头文件):
<type> funcName(parameters…){
//body instructions
}
•如果要创建DLL文件,请使用:
#include “dllcall.h”
然后在“dllcall.cpp”源文件中定义函数体(来自“dllcall.h”头文件)。同时,您可以从“dllexample.h”调用函数:
<type> funcName(parameters…){
//body instructions
}
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中的“解决方案资源管理器”,右键单击“属性”>“配置属性”>“C/C++”>“常规”>“其他包含目录”>添加64位“java/Include”和“java/Include/win32”路径(此选项将仅为当前Visual Studio项目的x64调试器设置)
5/将“dllcall.dll”和“dllexample.dll”复制到“workspace/dllcall/src”
•在“包资源管理器”中,右键单击“dlltest”>“属性”>“Java构建路径”>“源”>展开“my/Package/src”>选择“本机库位置”>“编辑”>添加“my/Package/src”作为位置路径
•使用以下方法导入“JNIClass.java”中的DLL文件:
static {
System.loadLibrary(“dllexample”);
System.loadLibrary(“dllcall”);
}
6/如果未选择64位JRE,则转到“运行”>“运行配置”>“JRE”>“备用JRE”>“已安装JRE”>放置64位Java JDK目录(应该类似于:“C:\Program Files\Java\JDK”,而32位Java JDK可以在“Program Files(x86)”文件夹中找到
7/完成
•现在您可以使用步骤2中定义的方法了您是否让loadKernel32返回true?@efekActive是的,它确实返回true。您可以看到它写着“Kernel32.dll loaded”在输出中是的。对不起。您是否厌倦了在详细模式下运行jvm以查看是否有任何有意义的消息?这不是
native
的工作方式;请参阅javah工具。使用JNI,您定义了应用程序所需的服务,并编写了一个DLL