Issue
I'm trying to invoke a C++ function from java that uses C++-style strings. The program executes just fine when I'm using C-style strings but just as I declare std::string somehow it can't find dependent libraries anymore. I checked my includes folder in eclipse environment and it does contain <string> library and all its dependencies.
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());
}
}
And this is my native file:
#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 !!");
}
This code compiles fine and runs well from java but as soon as I try to use the std::string version(commented) the code compiles and the dynamic library is created but on running the java code I get the following error:
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)
I have searched various sources for a possible explanation but couldn't find one. Guys, help me!
Solution
<string>
is a header file, and if your C++ code containing #include <string>
directive compiles this means that paths of standard include folders are configured correctly.
However, depending on how your project is configured to be linked to the C and C++ runtime libraries (statically or dynamically), the resulting executable may or may not depend on additional DLLs. (For example, in case of Microsoft Visual Studio 2019 C++ compiler, the C runtime library DLL is vcruntime140.dll
and C++ runtime library DLL is msvcp140.dll
.)
Using std::string
probably causes your executable to depend on the C++ runtime library DLL (in addition to the C runtime DLL), and perhaps it is not found in the same folder as the executable (and not in the DLL search path).
On Windows, C runtime DLL is often already available system-wide, but C++ runtime DLL needs to be either installed (using the Microsoft Visual C++ Redistributable package) or placed into the same folder along the executable itself.
Another option is to link runtime libraries statically, so the resulting executable won't have those DLL dependencies. But usually, dynamic linking is preferred.
Note that depending on which C++ compiler you are using with your Eclipse IDE — either GCC (G++), Clang, MSVC or some another — the required C++ runtime DLL will have a different filename.
Answered By - heap underrun