Windows JNI加载和执行c++;dll错误java.lang.UnsatifiedLinkError中的代码:
答案/解决方案:Jorn Vernee的答案是正确的,当我最初创建.h文件时,我在.java类中没有包信息,但当我的代码被执行时,它确实有包信息。.h文件中的方法名称最终将包括名称中的包信息 我有一些C++代码,我用它来截屏。我一直在尝试使用JNA和JNI从Java调用它,但两者都没有成功。我的最终目标是让captureScreen方法工作。我创建了一个getNumber方法,就像一个简单的测试一样,没有传入任何参数,但即使它也不起作用 更新我的应用程序以64位应用程序运行,我的dll为64位。不确定这是否会影响传入或传出的参数 我当前的实现 爪哇 我使用javac-h从上面的类创建头文件 .h文件Windows JNI加载和执行c++;dll错误java.lang.UnsatifiedLinkError中的代码:,java,c++,java-native-interface,Java,C++,Java Native Interface,答案/解决方案:Jorn Vernee的答案是正确的,当我最初创建.h文件时,我在.java类中没有包信息,但当我的代码被执行时,它确实有包信息。.h文件中的方法名称最终将包括名称中的包信息 我有一些C++代码,我用它来截屏。我一直在尝试使用JNA和JNI从Java调用它,但两者都没有成功。我的最终目标是让captureScreen方法工作。我创建了一个getNumber方法,就像一个简单的测试一样,没有传入任何参数,但即使它也不起作用 更新我的应用程序以64位应用程序运行,我的dll为64位。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNIScreenShot */
#include "DXGICapture.h"
#include <stdio.h>
#include <tchar.h>
#include <shlobj.h>
#include <atlconv.h>
#include <string>
using namespace std;
#ifndef _Included_JNIScreenShot
#define _Included_JNIScreenShot
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JNIScreenShot
* Method: captureScreen
* Signature: (Ljava/lang/String;IIII)V
*/
JNIEXPORT void JNICALL Java_JNIScreenShot_captureScreen
(JNIEnv*, jobject, jstring, jint, jint, jint, jint);
/*
* Class: JNIScreenShotTest
* Method: getNumber
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JNIScreenShotTest_getNumber
(JNIEnv*, jobject);
#ifdef __cplusplus
}
#endif
#endif
这会产生一个错误
java.lang.UnsatifiedLinkError:com.tdkc.udop.screencapture.jniScreenShot.captureScreen(Ljava/lang/string;IIII)V
起初,我认为我的captureScreen中有些东西失败了,或者可能是我传递的数据类型不同。所以我创建了getNumber方法作为测试
调用getNumber()时,我会遇到类似的错误
java.lang.UnsatisfiedLinkError:com.tdkc.udop.screencapture.jniScreenShot.getNumber()I
这两条错误消息都引用了.h文件中的签名,因此我知道它正在查找dll并试图调用正确的方法
花了一些时间查看未满足的LinkError,但大多数Google结果显示,当库加载时,我已经看到了很多,包括尝试使用System.loadLibrary()而不是System.load()时
它似乎可以找到方法,因为错误包含在my.h文件中为每个方法定义的签名
在这一点上,我已经尝试了以下关于JNI的指南和教程,已经2天了,我失去了任何帮助,非常感谢。从您的错误消息判断:
java.lang.UnsatisfiedLinkError: com.tdkc.udop.screencapture.jniScreenShot.getNumber()I
看来你们班的学生都很团结。但是,本机函数的名称与此不匹配:
Java_JNIScreenShotTest_getNumber
包名称也应该用本机函数的名称编码。从该错误消息来看,本机函数的名称应该是:
Java_com_tdkc_udop_screencapture_jniScreenShot_getNumber
使用
-Xlog:library*=trace
()可以看到VM用于查找的确切名称。例如:
[0.211s][info][library] Loaded library C:\Program Files\Java\jdk-15\bin\nio.dll, handle 0x00007ffacf0f0000
...
[0.212s][info][library] Found Java_sun_nio_fs_WindowsNativeDispatcher_initIDs in library with handle 0x00007ffacf0f0000
如果使用
-Xlog:library*=trace运行程序(需要JDK 15+),它会打印什么?您的库是否已成功加载?本机函数的符号查找是否搜索了正确的库?我不确定我是否理解您的要求。我的应用程序正在从Eclipse运行。这一行的快速谷歌没有告诉我它做什么,或者它在哪里保存文件,你能详细说明一下吗?这是VM参数吗?是的,这是VM参数。输出应在控制台中打印。这是一个选项,可以启用有关本机库加载和符号查找的额外日志记录。您可以在控制台中运行java-Xlog:help
(cmd/powershell/sh/bash,具体取决于您使用的平台/shell),或者查看在线文档:要获得关于VM参数的更多信息,我无法启动应用程序,我会得到一个java虚拟机启动器,然后出现一个Eclipse错误对话框,上面说Cannotconnect to VM。也就是说,它正在加载dll,因为它尝试调用时的错误消息与my.h文件中方法的签名匹配。输出应该告诉您是否正在加载正确的库(它打印路径),以及符号查找是否正在使用正确的名称查找正确的库。FWIW,对于查找来说,唯一重要的是函数名(DLL中没有类型信息,至少不典型)。您可以使用类似于dumpbin
(随Visual Studio提供)的内容,或者验证正在加载的DLL是否确实包含符号。要添加此内容,请始终重新创建标头并将实现更改为匹配,如果更改JNI包/类/方法名,这就是问题所在,因为.h文件是从没有包的java文件构建的。一旦我添加了包信息并让它重新生成.h文件,它就会更改我的方法名。虽然这解决了我的问题,但它留给我的另一个问题是,我假设如果java文件被移动,它将中断,并且无法找到正确的方法。有没有办法让.h文件方法名不包含包信息,这样,如果java文件移动了,它就不会影响它?@Jeremy不是真的,没有。您可能想看看API,它允许您手动链接本机函数,但需要先调用本机代码,第一次调用也会有相同的包命名问题。在我看来,这太麻烦了。至少在即将推出的ProjectPanama外部函数接口中,无需精确的名称映射,就可以更轻松地链接任意本机函数。
Java_JNIScreenShotTest_getNumber
Java_com_tdkc_udop_screencapture_jniScreenShot_getNumber
[0.211s][info][library] Loaded library C:\Program Files\Java\jdk-15\bin\nio.dll, handle 0x00007ffacf0f0000
...
[0.212s][info][library] Found Java_sun_nio_fs_WindowsNativeDispatcher_initIDs in library with handle 0x00007ffacf0f0000