我试图从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)
我已经搜索了各种可能的解释来源,但没有找到一个。伙计们,帮帮我!
2条答案
按热度按时间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将具有不同的文件名。
nvbavucw2#
非常感谢heap underrun的回答。我终于找到了一种方法来使它工作。我使用lucasg的Dependencies tool,发现 libgcc_s_seh-1.dll 和 libstdc++-6.dll 丢失,即使它们存在于MinGW bin中。
所以我把它们显式地添加到动态库所在的文件夹中,并将它们加载到java虚拟环境中。
注意:dll的加载顺序很重要。按其他顺序加载是行不通的。