为什么我的共享库 (dll) 没有正确链接到 stdc++-6.dll?

Why is my shared library (dll) not getting linked with the stdc++-6.dll properly?

所以我尝试使用 Jni 接口构建一个 dll 并将其加载到 Java 应用程序中,基本上我使用了一些由 Win32 API.

构建似乎很好,所有内容都已构建和链接。但是我无法弄清楚 stdc++-6.dll 是如何没有正确动态(共享)链接的,而其他事情是根据依赖管理器进行的,如图所示。

如果我尝试将 dll 加载到 java 应用程序中,我会得到

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

我尝试进行静态构建(只是想知道实际上并不需要静态构建),但随后显示

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

参考了SO中的几个问题,尝试调试

无济于事,因为我猜我所做的一切都是正确的,构建了 64 位 dll,并尝试将其加载到 64 位 Java-VM 中,依赖项检查器已经显示了所有链接的库也是 64 位的。

我也检查了 this unanswered question,它也承认当 dll 试图引用标准库或间接 std:: 接口时会出现问题,我没有使用过它们中的任何一个,但可能是windows 库正在间接使用它们(如果我通过 -nostdlib 编译失败,未解析的几个符号引用)

为了进行诊断,我附上了用于构建 dll 和构建输出(来自 CLI)的 Cmake 文件:

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

所以我终于找到了问题,特别感谢@zero9178 帮了我很多。

我实际上在 PATH 上安装了 32 位版本的 libstdc++-6.dll,它是由 MinGW 的官方版本安装的,因此从其他来源添加 64 位版本似乎可行。

我只有 new 关键字取决于该库,因为我曾经使用 #include <new> 中的 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 运算符检查它,其定义存在于 MSVCRT.dll(捆绑在 windows)。

所以没有冲突或需要静态 link 到(或捆绑)这么大的 header 只是为了使用其中的一些 keywords/functions。现在我能够生成小至 14Kb 的文件,但仍然能够使用 C++ 功能和库。虽然使用新的放置运算符不是一个好建议,但我还是使用了它,因为单个运算符是唯一的需要。