Eclipse中的JNI未满足链接错误无法找到相关库

zbwhf8kr  于 2022-11-04  发布在  Eclipse
关注(0)|答案(2)|浏览(203)

我试图从java调用一个C函数,它使用C风格的字符串。当我使用C风格的字符串时,程序执行得很好,但是就像我声明std::string一样,不知何故,它再也找不到依赖的库了。我在eclipse环境中检查了我的includes文件夹,它确实包含了库和它所有的依赖项。

package test_strings;

public class TestString {

    static {
        System.load("C:\\Users\\aurok\\eclipse-workspace\\native_cpp\\Debug\\libnative_cpp.dll");
    }

    public native String sayHelloC();
    public native String sayHelloCpp();

    public static void main(String[] args) {

        TestString test = new TestString();

        System.out.println(test.sayHelloC());
        System.out.println(test.sayHelloCpp());

    }

}

这是我的本机文件:


# include "test_strings_TestString.h"

# include<string>

using namespace std;

JNIEXPORT jstring JNICALL Java_test_1strings_TestString_sayHelloC
  (JNIEnv *env, jobject thisObj){

    jstring str = env->NewStringUTF("Hello World C-style !!");
    return str;
}

JNIEXPORT jstring JNICALL Java_test_1strings_TestString_sayHelloCpp
  (JNIEnv *env, jobject thisObj){
    //std::string str = "Hello World C++ style !!";
    //return env->NewStringUTF(str.c_str());
    return env->NewStringUTF("Hello World C++ style !!");
}

这段代码可以很好地编译,并且在java中运行良好,但是一旦我尝试使用std::string版本(注解),代码就会编译,并且动态库会被创建,但是在运行java代码时,我会收到以下错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\aurok\eclipse-workspace\native_cpp\Debug\libnative_cpp.dll: Can't find dependent libraries
    at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
    at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:383)
    at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:227)
    at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:169)
    at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2383)
    at java.base/java.lang.Runtime.load0(Runtime.java:746)
    at java.base/java.lang.System.load(System.java:1857)
    at test_strings.TestString.<clinit>(TestString.java:6)

我已经搜索了各种可能的解释来源,但没有找到一个。伙计们,帮帮我!

vvppvyoh

vvppvyoh1#

<string>是一个头文件,如果包含#include <string>指令的C代码编译,这意味着标准包含文件夹的路径配置正确。
但是,根据您的项目配置为链接到C和C
运行时库的方式(静态或动态),生成的可执行文件可能依赖于也可能不依赖于其他DLL。(例如,对于Microsoft Visual Studio 2019 C编译器,C运行时库DLL为vcruntime140.dll,而C运行时库DLL为msvcp140.dll
使用std::string可能会导致可执行文件依赖于C运行时库DLL(除了C运行时DLL之外),并且可能无法在可执行文件所在的文件夹中找到它(并且不在DLL搜索路径中)。
在Windows上,C运行时DLL通常已在系统范围内可用,但C
运行时DLL需要安装(使用Microsoft Visual C可再发行软件包)或沿着可执行文件放在同一文件夹中。
另一种选择是静态链接运行库,这样生成的可执行文件就不会有那些DLL依赖项。
请注意,根据您在Eclipse IDE中使用的C
编译器(GCC(G++)、Clang、MSVC或其他编译器),所需的C++运行时DLL将具有不同的文件名。

nvbavucw

nvbavucw2#

非常感谢heap underrun的回答。我终于找到了一种方法来使它工作。我使用lucasgDependencies tool,发现 libgcc_s_seh-1.dlllibstdc++-6.dll 丢失,即使它们存在于MinGW bin中。
所以我把它们显式地添加到动态库所在的文件夹中,并将它们加载到java虚拟环境中。

package test_strings;

import java.io.IOException;

public class TestString {

    static {
        System.load("C:\\Users\\aurok\\eclipse-workspace\\native_cpp\\Debug\\libwinpthread-1.dll");
        System.load("C:\\Users\\aurok\\eclipse-workspace\\native_cpp\\Debug\\libgcc_s_seh-1.dll");
        System.load("C:\\Users\\aurok\\eclipse-workspace\\native_cpp\\Debug\\libstdc++-6.dll.dll");
        System.load("C:\\Users\\aurok\\eclipse-workspace\\native_cpp\\Debug\\libnative_cpp.dll");
    }

    public native String sayHelloC();
    public native String sayHelloCpp();

    public static void main(String[] args) {

        TestString test = new TestString();

        System.out.println(test.sayHelloC());
        System.out.println(test.sayHelloCpp());

    }

}

注意:dll的加载顺序很重要。按其他顺序加载是行不通的。

相关问题