2023-01-20 391
tl; dr:C ++插件需要致电Java .jar库.如何将其部署给没有太多头痛的用户?
我正在为QT应用程序编写QT插件.该插件需要拨打到现有的Java库.这需要工作跨平台(Win,Mac,Linux)和体系结构(32位和64位Intel,无PPC).
我得到了一个简单的” Hello World” JNI示例编译和运行.我将cmake脚本更新为” find_package(jni criuns)”等.因此,它针对jni.h标题进行了编译,并针对JVM库动态链接.
至少在Windows上,Cmake在查找合适的JVM时做得很好.它在运行时发现了合适的JRE(JVM.DLL等),因为我对用户的计算机的控制权较少.
当我将插件发送给用户时,它将如何工作?他们将需要安装JRE来进行适当的体系结构.但这并不意味着JRE LIB目录(IES)将在他们的道路上.如果不是,则插件只是释放而不会加载.
在Windows上,64位JDK安装JVm.dll似乎也很麻烦:
C:\Program Files\Java\jre7\bin\server\jvm.dll
但是32位JDK将其安装到:
C:\Program Files (x86)\Java\jre7\bin\client\jvm.dll
我了解PF与PFX86的差异,但是我没有得到的服务器/客户端.这些实际上是不同的jres吗?
如果我已经针对一个JRE版本进行了编译/链接,并且用户具有不同的版本?
我认为这在Linux/Mac上都会更容易,但是我还没有走那么远.
任何帮助将不胜感激.我与使用JNI不匹配,但不能负担2000美元的编译器将Java变成本地代码库(无论如何我都有来源),而且我听说GCJ可能无法完成任务(也许可能是在Windows上无济于事).
仅适用于Windows的解决方案.
请参阅 delayloflow”> delaylload 为此,它只是将/DELAYLOAD:jvm.dll和Delayimp.lib添加到链接器命令中.这意味着在加载QT插件时不会加载jvm.dll,但在需要时(请注意,它 not 需要使用LoadLibrary()和GetProcAddress()). (我不知道Linux或Mac上是否有类似的功能)
这可以是专门针对插件的注册表值,配置文件或环境变量(绝对不是环境变量JAVA_HOME或JRE_HOME其他应用程序可能依赖的).示例环境变量:
在QT插件调用取决于JRE的任何函数之前,它会通过插入%DANQT_32_JRE_HOME%\bin\server;%DANQT_32_JRE_HOME%\bin\client;在PATH的值开始时修改其PATH环境变量.这意味着,当QT插件执行其第一个操作时,需要将JRE从插入的目录加载. (64位的不同环境变量).至于bin\client和bin\client我的理解是,这些基本相同,但出于运行时性能原因,server在初始化过程中执行更多.
如果安装了JRE 6和JRE 7的QT插件,我不确定兼容性.如果存在兼容性问题,则将其作为先决条件要求,或者,如果允许(我不确定合法性),请使用QT插件运送jvm.dll.
需要添加到 @HMJD的答案中的一些更详细的注释,其中很多细节使我绊倒了.
这是我用来编译和链接测试程序的命令行:
cl
-I"C:\Program Files (x86)\Java\jdk1.7.0_02\include"
-I"C:\Program Files (x86)\Java\jdk1.7.0_02\include\win32"
/EHsc
-MD
Test.cpp
jvm.lib
delayimp.lib
/link
/LIBPATH:"C:\Program Files (x86)\Java\jdk1.7.0_02\lib"
/DELAYLOAD:jvm.dll
要注意的几件事:
在.cpp文件中,#include “windows.h”,找出哪个目录具有jvm.dll,然后拨打这样的呼叫:
std::string temp = "C:\\Program Files (x86)\\Java\\jdk1.7.0_02\\jre\\bin\\client";
SetDllDirectory(temp.c_str());
在调用库中的任何函数之前就这样做,因此,当称为LoadLibrary()时,它就会知道在哪里找到DLL.另一种选择是用SetEnvironmentVariable()修改PATH变量,但SetDllDirectory()似乎是一个更好的选择.
在您的启动代码中的某个地方,添加这样的代码:
__try
{
// call a function from the DLL to make sure it can be loaded
::JNI_CreateJavaVM(...);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// If not, fail
}
最好将其放在自己的功能中,因为__try/__except结构化异常处理(SEH)内容不忍受与可能会放松对象的代码共享函数.
没有SEH的内容,如果找不到DLL,该程序就会崩溃.
一些有用的链接:
打开链接旗
由于我无法在Linux上找到等同于/DELAYLOAD的等效物(在此处问:我如何使懒惰/延迟加载在linux中工作?),我使用dlopen()被卡住了. It’s not as bad as I thought it would be — I can use the technique described here: c ++ 中dlsym()和dlopen()的替代方案.实际上,似乎JNI.H标头是为此方法设计的.也许我首先也应该在窗户上做的事情.
以上所述是小编给大家介绍的如何部署一个混合的C++/Java(JNI)应用程序?,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!
原文链接:https://77isp.com/post/26003.html
=========================================
https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。
数据库技术 2022-03-28
网站技术 2022-11-26
网站技术 2023-01-07
网站技术 2022-11-17
Windows相关 2022-02-23
网站技术 2023-01-14
Windows相关 2022-02-16
Windows相关 2022-02-16
Linux相关 2022-02-27
数据库技术 2022-02-20
抠敌 2023年10月23日
嚼餐 2023年10月23日
男忌 2023年10月22日
瓮仆 2023年10月22日
簿偌 2023年10月22日
扫码二维码
获取最新动态