Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从C+;执行Java的简单性+;_Java_C++_Visual C++_User Interface_Java Native Interface - Fatal编程技术网

从C+;执行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文件(我认为这是最合

背景信息:我习惯用Java编程,我知道如何使用Eclipse和Visual Studio

最终目标:创建一个GUI,最好是在VisualStudio中,它执行Java函数

我想从这个问题中得到一个按钮:C++,点击,执行java函数并返回结果到C++。(可能通过调用JVM)

我目前考虑了以下数据结构:

  • 通过“公共”文件(如.txt文件)共享数据(但如何启动Java函数?)
  • 打开插座(对于这个问题来说似乎太复杂)
  • 通过服务器连接(太复杂)
  • 从C++调用JVM,然后执行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>);