使用 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) 中使用的主要内容,如果未能解决你的问题,请参考以下文章
在Linux下使用MinGW静态交叉编译带有zlib的libcurl(包括交叉编译openssl,即--cross-compile-prefix=i686-w64-mingw32- mingw)(代码