从C+;执行Java的简单性+;
背景信息:我习惯用Java编程,我知道如何使用Eclipse和Visual Studio 最终目标:创建一个GUI,最好是在VisualStudio中,它执行Java函数从C+;执行Java的简单性+;,java,c++,visual-c++,user-interface,java-native-interface,Java,C++,Visual C++,User Interface,Java Native Interface,背景信息:我习惯用Java编程,我知道如何使用Eclipse和Visual Studio 最终目标:创建一个GUI,最好是在VisualStudio中,它执行Java函数 我想从这个问题中得到一个按钮:C++,点击,执行java函数并返回结果到C++。(可能通过调用JVM) 我目前考虑了以下数据结构: 通过“公共”文件(如.txt文件)共享数据(但如何启动Java函数?) 打开插座(对于这个问题来说似乎太复杂) 通过服务器连接(太复杂) 从C++调用JVM,然后执行java文件(我认为这是最合
我想从这个问题中得到一个按钮:C++,点击,执行java函数并返回结果到C++。(可能通过调用JVM)
我目前考虑了以下数据结构:- 通过“公共”文件(如.txt文件)共享数据(但如何启动Java函数?)
- 打开插座(对于这个问题来说似乎太复杂)
- 通过服务器连接(太复杂)
Jace
、JNI
和SWIG
的存在,但我认为它们非常适合制作复杂的程序,而不是简单的界面。我不想做一个复杂的程序,因此我觉得学习他们所有的命令很麻烦
我也读过很多关于堆栈交换的问题,问的都是同样的问题,但它们似乎都给出了非常复杂的答案
所以我的问题是:
< C++ >执行C++(如果需要的话:预编译)java函数的绝对简单方法是什么?C++代码将一些参数传递给这个java函数< /St>>/P>
提前谢谢
从C++调用JVM,然后执行java文件(我认为这是最合理的方法,但这需要很多代码)
是的,这绝对是最合理的方式。对于JNI和Java,它甚至没有那么多代码 查找jvm.dll 您可以尝试硬编码Oracle JVM的JVM.dll的路径
,或者在programs文件夹中搜索名为JVM.dll
的文件,但所有这些显然都是非常粗糙的。然而,显然有一个非常简单的解决方案:注册表。键HKEY\U LOCAL\U MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
包含一个名为CurrentVersion
的REG\u SZ
。您可以读取该键的值(当前为1.7
),然后打开具有该名称的子键(本例中为HKEY\U LOCAL\U MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.7
)。然后,该键将包含一个名为RuntimeLib
的REG_SZ
,它是到jvm.dll
的路径。不要担心程序文件
vs程序文件(x86)
。如果您是64位windows上的32位进程,并且该项包含指向32位jvm.dll
的路径,则WOW64将自动将注册表查询重定向到HKLM\SOFTWARE\Wow6432Node
。代码:
#include <Windows.h>
#include <jni.h> // C:\Program Files\Java\jdk1.7.0_10\include\jni.h
// ...
DWORD retval;
// fetch jvm.dll path from registry
HKEY jKey;
if (retval = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\JavaSoft\\Java Runtime Environment"), 0, KEY_READ, &jKey))
{
RegCloseKey(jKey);
// assuming you're using C++/CLI
throw gcnew System::ComponentModel::Win32Exception(retval);
}
TCHAR versionString[16]; // version numbers shouldn't be longer than 16 chars
DWORD bufsize = 16 * sizeof(TCHAR);
if (retval = RegGetValue(jKey, NULL, TEXT("CurrentVersion"), RRF_RT_REG_SZ, NULL, versionString, &bufsize))
{
RegCloseKey(jKey);
// assuming you're using C++/CLI
throw gcnew System::ComponentModel::Win32Exception(retval);
}
TCHAR* dllpath = new TCHAR[512];
bufsize = 512 * sizeof(TCHAR);
retval = RegGetValue(jKey, versionString, TEXT("RuntimeLib"), RRF_RT_REG_SZ, NULL, dllpath, &bufsize)
RegCloseKey(jKey);
if (retval)
{
delete[] dllpath;
// assuming you're using C++/CLI
throw gcnew System::ComponentModel::Win32Exception(retval);
}
创建JVM
现在您可以调用该函数:
JavaVMInitArgs initArgs;
initArgs.version = JNI_VERSION_1_6;
initArgs.nOptions = 0;
JavaVM* jvm;
JNIEnv* env;
if ((retval = createJavaVM(&jvm, &env, &initArgs)) != JNI_OK)
throw gcnew System::Exception(); // beyond the scope of this answer
恭喜你!现在有一个JVM正在您的进程中运行!您可能会在应用程序启动时启动JVM。除非您100%确信只能从刚刚创建JVM的线程调用Java代码,否则您可以扔掉env
指针,但必须保留JVM
指针
获取JNI环境(可选)
现在,您创建了JVM,应用程序启动并运行,然后有人单击该按钮。现在您需要调用Java代码。如果您100%确信您现在在上一步中创建JVM的线程上,并且仍然有env
指针,那么您可以跳过此步骤。否则,快速检查当前线程是否已连接到JVM,如果未连接到JVM,则进行连接:
JNIEnv* env;
bool mustDetach = false;
jint retval = jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
if (retval == JNI_EDETACHED)
{
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6;
args.name = NULL;
args.group = NULL;
retval = jvm->AttachCurrentThread(&env, &args);
mustDetach = true; // to clean up afterwards
}
if (retval != JNI_OK)
throw gcnew System::Exception(); // should never happen
invokeJavaCode(env); // next step
if (mustDetach)
jvm->DetachCurrentThread();
调用Java代码
现在您就在这里,您希望调用该Java代码,甚至还有env
指针。您需要最简单的解决方案,因此以下是调用静态方法的方式:
jclass clazz = env->FindClass("com/myself/MyClass");
if (clazz == NULL)
throw gcnew System::Exception();
jmethodID mid = env->GetStaticMethodID(clazz, "myStaticMethod", "<signature>");
if (mid == NULL)
throw gcnew System::Exception();
<type> returnedValue = env->CallStatic<type>Method(clazz, mid, <arguments>);
jclass clazz=env->FindClass(“com/imf/MyClass”);
if(clazz==NULL)
抛出新系统::异常();
jmethodID mid=env->GetStaticMethodID(clazz,“myStaticMethod”和“”);
if(mid==NULL)
抛出新系统::异常();
returnedValue=env->CallStaticMethod(clazz,mid,);
您可以使用javap-s
(命令行工具)来确定方法的签名<代码>可以是任何基元类型(它必须与Java方法的返回类型匹配)。参数可以是任何基元类型,只要它们与Java方法的参数匹配
结局
<> p>并且有:从Windows上调用C++的java代码最简单的方法(实际上只有前两部分是Windows专用的……)。哦,也是最有效的。拧紧数据库和文件。使用
127.0.0.1
sockets将是一种选择,但这会大大降低效率,并且可能不会比这少做工作。哇,这个答案比我预期的要长一点。希望能有所帮助。第二个问题在SO中有很多问题。此问题链接到其中一些问题:。(我个人使用exe4j)是的,我也读过这些问题。但是java C++的C++语言可以执行,但不能让它成为一个“好”(Visual C++ +好)接口。“界面与VisualC++可以做的一样”——你是指类似的吗?通过<代码>系统::对象^ < /C> >你在谈论C++ + CLI(这不是C++),对吗?也许这能帮上忙?jni4net库?这个答案太棒了!你完全回答了我的问题,并清楚地阐述了每一步!非常感谢你!
jclass clazz = env->FindClass("com/myself/MyClass");
if (clazz == NULL)
throw gcnew System::Exception();
jmethodID mid = env->GetStaticMethodID(clazz, "myStaticMethod", "<signature>");
if (mid == NULL)
throw gcnew System::Exception();
<type> returnedValue = env->CallStatic<type>Method(clazz, mid, <arguments>);