使用 MinGW C++ 编译 64 位静态库以在 Java (JNI) 中使用

Posted

技术标签:

【中文标题】使用 MinGW C++ 编译 64 位静态库以在 Java (JNI) 中使用【英文标题】:Compiling a 64bit static lib with MinGW C++ for usage in Java (JNI) 【发布时间】:2014-03-09 14:09:32 【问题描述】:

这个问题与JNI %1 is not a valid Win32 application 类似的问题。

我还想从 C++ 源代码编译一个 64 位静态库以在 Java 中使用,我也收到错误:

Exception in thread "Thread-2" java.lang.UnsatisfiedLinkError: C:\Users\boon\AppData\Local\Temp\keyboardhook-3382807930283923158.lib: %1 is no valid Win32 application at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(Unknown Source) at java.lang.ClassLoader.loadLibrary(Unknown Source) at java.lang.Runtime.load0(Unknown Source) at java.lang.System.load(Unknown Source) at de.ksquared.system.keyboard.Native.load(Native.java:79) at de.ksquared.system.keyboard.KeyboardHook.(KeyboardHook.java:84) at de.ksquared.system.keyboard.PoolHook.run(KeyboardHook.java:51)

而我想从 Kristian Kraljic (http://kra.lc/blog/2011/07/java-global-system-hook/) 编译 KeyboardHook,并在库中添加一些功能。首先,我尝试使用 Microsoft Visual Studio 2013 编译我的 KeyboardHook.cpp,但 Kristian 建议的编译标志都被忽略了,我也遇到了上面提到的相同异常。因此我将编译器更改为MinGW,并使用以下命令编译成功:

g++ -Wall -c -D_JNI_IMPLEMENTATION_ -Wl,-kill-at -O0 -g3 -fmessage-length=0 -static-libgcc -I”%JAVA_HOME%\include” -m64 -I”%JAVA_HOME%\include \win32″ -shared -o keylib.lib KeyboardHook.cpp

我从克里斯蒂安的建议中接手的大部分旗帜。问题似乎是生成的 .lib 文件似乎仍然不是完全 64 位的。 gcc -dumpmachine 告诉我:x86_64-w64-mingw32,因此应该可以使用 32 位和 64 位作为目标。使用标志-m64 它应该使用 64 位编译,但是还是?我正在使用 minGW build x64-4.8.1-win32-seh-rev5,Windows 7 64bit 和 Java7。

目前我不知道我还能在哪里找到错误。我必须以不同的方式设置链接器标志吗?

【问题讨论】:

您需要将-static-libstdc++ 添加到标志中。为什么?因为如果您尝试使用LoadLibrary("Myplugin.dll") 加载您的.dll,您会注意到它找不到某些库。或者您需要将Mingw64/bin 添加到您的%PATH%。另一件事是确保您的 JVM 是 64 位的。所以再一次,从 64 位可执行文件中尝试LoadLibrary 你自己的插件,看看它是否加载。然后用 Java 尝试它。 您同时使用-static-libgcc-shared?我以为你想要一个静态库? 您能否使用objdump 确定您的.dll 需要哪些外部符号? 从错误消息中,Java 需要一个 DLL(动态库)而不是静态库。出现该错误消息时您在做什么,为什么您认为需要静态库? 首先非常感谢大家的帮助。 CantChooseUsernames,现在可以运行了,谢谢一百万。我添加了标志-static-libstdc++ 和编译工作。关于动态/静态库的问题,我不得不承认我对此知之甚少,我在运行时开始时使用System.load() 加载库,目前是一个静态库(.lib)。我想我可以省略-shared 那么? 【参考方案1】:

在我自己的项目中,我使用以下标志:

-static-libgcc          # Don't require to ship libgcc_s_seh-1.dll with your dll
-static-libstdc++       # Don't require to ship libstdc++-6.dll
-shared                 # As usual. Yeah, static+shared, Windows is beautiful
-Wl,--add-stdcall-alias # The JVM expects _stdcall decoration while mingw produces
                        #  _cdecl. You could use -Wl,-kill-at but this one is clear
-m64                    # I need 64 bits binary code for my 64 bits JVM

我的完整代码可用on GitHub。

【讨论】:

以上是关于使用 MinGW C++ 编译 64 位静态库以在 Java (JNI) 中使用的主要内容,如果未能解决你的问题,请参考以下文章

windows中使用mingw64编译dlib的c++

MinGW64位32位问题求教

如何配置 python cffi 库以使用 mingw?

在Linux下使用MinGW静态交叉编译带有zlib的libcurl(包括交叉编译openssl,即--cross-compile-prefix=i686-w64-mingw32- mingw)(代码

利用Code::Blocks搭建64位C++开发平台

Msys2+mingw-w64 编译VS2013使用的ffmpeg静态库注意事项