简体   繁体   English

Windows JNI 加载并执行 dll 中的 c++ 代码错误 Z93F725A07423FE1C889F448B33DsfiedLinkError:648B33DsfiedLinkError:6

[英]Windows JNI Loading and executing c++ code in dll error java.lang.UnsatisfiedLinkError:

Answer/Solution: To be clear Jorn Vernee's answer is correct in that when i created my.h file originally i didnt have the package information in the.java class but when my code was executed it did have the package information. Answer/Solution: To be clear Jorn Vernee's answer is correct in that when i created my.h file originally i didnt have the package information in the.java class but when my code was executed it did have the package information. The method names in the.h file will end up including the package information in the name. .h 文件中的方法名称最终会在名称中包含 package 信息。

I've got some C++ code that i use to take a screen shot.我有一些 C++ 代码用于截屏。 I've been attempting to call it from Java using both JNA and JNI and having no luck with either.我一直在尝试使用 JNA 和 JNI 从 Java 调用它,但都没有运气。 My ultimate goal is to get the captureScreen method working.我的最终目标是让 captureScreen 方法工作。 I created a getNumber method just as a simple test with no parameters passed in but even it wouldnt work.我创建了一个 getNumber 方法作为一个简单的测试,没有传入任何参数,但即使它也不起作用。

Update My application is running as a 64 bit application and my dll is 64 bit.更新我的应用程序作为 64 位应用程序运行,而我的 dll 是 64 位的。 Not sure if that affects the parameters passed in or out.不确定这是否会影响传入或传出的参数。

My current implementation我目前的实现

Java Java

public class JNIScreenShotTest { 
   static {
  String oldLibraryPath = System.getProperty("java.library.path");
  try{
  //This doesnt work for me it fails on the loadLibrary call and I get an UnsatisfiedLinkError
  //System.setProperty("java.library.path", "C:\\workspace\\com.tdkc.udop\dlls");
  //System.loadLibrary("JNIScreenShot"); 
                               
  //This Manages to load the library without error                         
  System.load("C:\\workspace\\com.tdkc.udop\\dlls\\JNIScreenShot.dll")
  }finally}
      System.setProperty("java.library.path", oldLibraryPath );
  }
 }

  private native void captureScreen(String filePath, int x, int y, int width, int height);

  private native int getNumber();

}

I used javac -h to create my header file from the above class我使用 javac -h 从上面的 class 创建了我的 header 文件

.h file .h 文件

    /* 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

C++ file C++文件

    // ScreenCapture.cpp : Defines the exported functions for the DLL.
//


#include "JNIScreenShot.h"
#include <iostream>


JNIEXPORT void JNICALL Java_JNIScreenShot_captureScreen
(JNIEnv *env, jobject clz, jstring filePath, jint x, jint y, jint width, jint height) {
    HRESULT hr = S_OK;
    CDXGICapture dxgiCapture;
    jboolean isCopy;
    const char* pszOutputFileName = (env)->GetStringUTFChars(filePath, &isCopy);

    hr = dxgiCapture.Initialize();
    tagScreenCaptureFilterConfig config;

    // set default config
    RtlZeroMemory(&config, sizeof(config));
    config.ShowCursor = 1;
    config.SizeMode = tagFrameSizeMode_AutoSize;

    hr = dxgiCapture.SetConfig(config);
    hr = dxgiCapture.CaptureToFile((LPCTSTR)CA2WEX<>(pszOutputFileName), x, y, width, height);
    if (FAILED(hr))
    {
        printf("Error[0x%08X]: CDXGICapture::CaptureToFile failed.\n", hr);
    }
}

/*
 * Class:     JNIScreenShotTest
 * Method:    getNumber
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_JNIScreenShotTest_getNumber
(JNIEnv *env, jobject clz) {
    return 2;
}

My calls from java are as follows我来自 java 的电话如下

File f = new File("Some file");
int x = some value;
int y = some value;
int width = some value;
int height = some value;

JNIScreenShot jniScreenShot = new JNIScreenShot();
jniScreenShot.(f.getAbsolutePath(), x,y,width,height)

This generates an error java.lang.UnsatisfiedLinkError: com.tdkc.udop.screencapture.jniScreenShot.captureScreen(Ljava/lang/string;IIII)V这会产生错误 java.lang.UnsatisfiedLinkError: com.tdkc.udop.screencapture.jniScreenShot.captureScreen(Ljava/lang/string;IIII)V

At first i thought something in my captureScreen was failing or maybe it was a difference in data types i was passing in. So i created the getNumber method as a test起初我认为我的 captureScreen 中的某些东西失败了,或者可能是我传入的数据类型不同。所以我创建了 getNumber 方法作为测试

I get a similar error when calling getNumber() java.lang.UnsatisfiedLinkError: com.tdkc.udop.screencapture.jniScreenShot.getNumber()I调用 getNumber() java.lang.UnsatisfiedLinkError: com.tdkc.udop.screencapture.jniScreenShot.getNumber()I 时出现类似错误

Both of the error messages reference the Signature in the.h file so i know its finding the dll and attempting to call the right method.两条错误消息都引用了 .h 文件中的签名,所以我知道它找到了 dll 并尝试调用正确的方法。

Spent some time looking at the UnsatisfiedLinkError but most googled results show that when the library is loading which i've seen plenty of including when trying to use System.loadLibrary() instead of System.load()花了一些时间查看 UnsatisfiedLinkError 但大多数谷歌搜索结果表明,当库正在加载时,我已经看到很多包括尝试使用 System.loadLibrary() 而不是 System.load()

It would appear that its finding the methods ok as the error contains the signature defined in my.h file for each method.它似乎可以找到方法,因为错误包含在 my.h 文件中为每个方法定义的签名。

At this point i've tried following what seems like a million guides and tutorials on JNI and its been 2 days and i'm lost any help is greatly appreciated.在这一点上,我已经尝试遵循关于 JNI 的一百万个指南和教程,并且已经 2 天了,我失去了任何帮助,非常感谢。

Judging from your error message:从你的错误信息来看:

java.lang.UnsatisfiedLinkError: com.tdkc.udop.screencapture.jniScreenShot.getNumber()I

It seems that your class is in a package.您的 class 似乎在 package 中。 But, the name of your native function doesn't match this:但是,您的本地 function 的名称与此不匹配:

Java_JNIScreenShotTest_getNumber

The package name should be encoded in the name of the native function as well. package 名称也应编码为原生 function 的名称。 From that error message, it looks like the name of your native function should be:从该错误消息来看,您的本机 function 的名称应该是:

Java_com_tdkc_udop_screencapture_jniScreenShot_getNumber

Using -Xlog:library*=trace ( since JDK 15 ) you could see the exact name the VM is using for the lookup.使用-Xlog:library*=trace从 JDK 15 开始),您可以看到 VM 用于查找的确切名称。 For instance:例如:

[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

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

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