【问题标题】:Why is my shared library (dll) not getting linked with the stdc++-6.dll properly?为什么我的共享库 (dll) 没有与 stdc++-6.dll 正确链接?
【发布时间】:2021-04-28 04:55:30
【问题描述】:

所以我尝试使用 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 lib 或间接引用 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

【问题讨论】:

  • libstdc++-6.dll 不是与 Windows 捆绑在一起的库,因此您必须确保它位于 standard DLL search path 上(例如,将包含该库的目录添加到 PATH 变量中)跨度>
  • 您还需要确保您使用的是与您的 JVM 相同的 C++ 运行时库。请参阅C++ JNI crashes/hangs when doing any IO/Streams,了解如果链接到与 JVM 使用的不同的 C++ 运行时库会发生什么情况的示例。

标签: java c++ windows dll java-native-interface


【解决方案1】:

所以我终于找到了问题所在,特别感谢@zero9178 对我的帮助很大。

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

我只有 new 关键字依赖于该库,因为我曾经使用 dependency walker 检查它。因此,我没有包含整个库(大小为 2MB),而是在 std-lib 中提供了所有 C++ 功能,我只使用了 #include &lt;new&gt; 中的 malloc 和 new placement 运算符,其定义存在于 @ 987654327@(在windows中捆绑)。

因此没有冲突或需要静态链接到(或捆绑)如此大的标题只是为了使用其中的一些关键字/功能。现在我能够生成小至 14Kb 的文件,仍然能够使用 C++ 功能和库。虽然使用新的放置操作符不是一个好建议,但我使用它是因为唯一需要单个操作符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-17
    • 2015-10-05
    • 2011-11-11
    • 2011-09-09
    • 1970-01-01
    • 2019-10-01
    相关资源
    最近更新 更多