0

So I was trying to build and load a dll into a Java application using the Jni interface, and basically I've used a few libraries consisting of the Win32 API.

The build seems to be fine, everything built and linked. But I'm not able to figure out how is the stdc++-6.dll is not getting dynamically (shared) linked properly, while other things do according to the dependency manager as shown.

dependency manager snapshot

If I try to load the dll into the java application, I get

java.lang.UnsatisfiedLinkError: C:\<path-to-dll>\libKeyboardKtx64.dll: %1 is not a valid Win32 application

I tried to do a static build (just to know not actually want a static build), but then it says

java.lang.UnsatisfiedLinkError: C:\<path-to-dll>\libKeyboardKtx64.dll: Can't find dependent libraries.

Referencing a few questions in SO, I tried debugging

Neither help, because I've did everything correctly I guess, built 64-bit dll, and trying to load it in a 64-bit Java-VM and already the dependencies inspector shows all linked libraries are 64-bit as well.

I also checked this unanswered question, it also admits the problem happens when the dll tries to reference the std lib or indirectly std:: interface, I haven't used any of them, but probably the windows libraries are using them indirectly (if I pass -nostdlib compilation fails with unresolved reference of few symbols)

For the diagnosis, I'm attaching the Cmake file I used to build the dll and build output (from the CLI):

cmake_minimum_required(VERSION 3.10)
project(KeyboardKt)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s")

option(ARCH "architecture")

add_definitions(-D_WIN32_WINNT=0x600)

include_directories($ENV{JNI_HEADERS_DIR})
include_directories("../../generated/jni")
include_directories("../../../nativeCommon/windows")


add_library(
    KeyboardKt${ARCH} SHARED
    JvmKeyboardHandler.cpp
)
== Using MXE wrapper: /usr/src/mxe/usr/bin/x86_64-w64-mingw32.shared-cmake
     - cmake version 3.19.2
     - warnings for unused CMAKE_POLICY_DEFAULT variables can be ignored
== Using MXE toolchain: /usr/src/mxe/usr/x86_64-w64-mingw32.shared/share/cmake/mxe-conf.cmake
== Using MXE runresult: /usr/src/mxe/usr/share/cmake/modules/TryRunResults.cmake
== Adding "-DCMAKE_BUILD_TYPE=Release"
loading initial cache file /usr/src/mxe/usr/share/cmake/modules/TryRunResults.cmake
-- The C compiler identification is GNU 10.2.0
-- The CXX compiler identification is GNU 10.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/src/mxe/usr/bin/x86_64-w64-mingw32.shared-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/src/mxe/usr/bin/x86_64-w64-mingw32.shared-g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /work/project/build/tmp/compile-jni-windows-x64
== Using MXE wrapper: /usr/src/mxe/usr/bin/x86_64-w64-mingw32.shared-cmake
== Skip using MXE toolchain: /usr/src/mxe/usr/x86_64-w64-mingw32.shared/share/cmake/mxe-conf.cmake
Scanning dependencies of target KeyboardKtx64
[ 50%] Building CXX object CMakeFiles/KeyboardKtx64.dir/JvmKeyboardHandler.cpp.obj
[100%] Linking CXX shared library libKeyboardKtx64.dll
[100%] Built target KeyboardKtx64
Animesh Sahu
  • 7,445
  • 2
  • 21
  • 49
  • `libstdc++-6.dll` is not a library that's bundled with Windows, so you have to make sure that it's on the [standard DLL search path](https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#standard-search-order-for-desktop-applications) (e.g. by adding the directory that contains the library to the PATH variable) – Jorn Vernee Jan 24 '21 at 11:49
  • You also need to make sure you're using the same C++ runtime library that your JVM is using. See [**C++ JNI crashes/hangs when doing any IO/Streams**](https://stackoverflow.com/questions/39709501/c-jni-crashes-hangs-when-doing-any-io-streams) for an example of what can happen if you link to a different C++ runtime library than the JVM uses. – Andrew Henle Jan 24 '21 at 15:20

1 Answers1

0

So I finally figured out the problem, special thanks to @zero9178 which helped me alot.

I actually had 32-bit version of the libstdc++-6.dll on the PATH which was installed by the official build of MinGW so adding a 64-bit from other sources seems to work.

I had only the new keyword depends on that library as I used to inspect it with the dependency walker. So instead of including the whole library (of 2MB in size), as all the C++ features are available out of the std-lib I just used the malloc and the new placement operator from the #include <new> whose definition is present in the MSVCRT.dll (bundled in windows).

So there is no conflict or need to statically link to (or bundle) such a large header just to use some of the keywords/functions from it. Now I was able to produce as small as 14Kb still able to use the C++ features and libraries. Although its not a good advice to use the new placement operator, I used it since single operator was the only one need.

Animesh Sahu
  • 7,445
  • 2
  • 21
  • 49