【问题标题】:Specifying the Path in a C++ Program在 C++ 程序中指定路径
【发布时间】:2019-05-03 06:26:54
【问题描述】:

我正在为 Windows 编写一个 Java 启动器,该启动器针对位于我的程序目录中的 Java 运行时环境启动(即随我的程序一起分发)。我有有效的代码(在下面指定),但它需要 jvm.dll 在其 %PATH% 中才能执行。

我想在我的代码中添加一行,告诉程序在<executable's directory>/jre/bin/server 中签入jvm.dll,这样可执行文件只需双击即可运行。

现在当我运行它时,它说“程序无法启动,因为您的计算机中缺少 jvm.dll。请尝试重新安装程序以解决此问题。”

如果我将我的简单可执行文件移动到jvm.dll 所在的jre\bin\server 并尝试运行它,它就可以工作。 所以我只需要告诉我的程序在特定的其他地方搜索 dll 就可以了。

根据我通过搜索找到的东西,我尝试了HINSTANCE hVM = LoadLibrary("jre\\bin\\server\\jvm.dll");。不幸的是,这不起作用。

我怎样才能实现这个目标?我不是 C 程序员或 Windows 程序员,如果问题是基本的,我深表歉意。

#include <jni.h> 
#include <windows.h>

int main() {
   HINSTANCE hVM = LoadLibrary("jre\\bin\\server\\jvm.dll"); //Does not work

   JavaVM *jvm; 
   JNIEnv *env;
   JavaVMInitArgs vm_args; 
   JavaVMOption* options = new JavaVMOption[1];

   int index = 0;
   options[index].optionString = (char *)"-Djava.class.path=./main.jar";

   vm_args.version = JNI_VERSION_10;
   vm_args.nOptions = 1;
   vm_args.options = options;
   vm_args.ignoreUnrecognized = false;
   JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
   delete options;

   jmethodID main = NULL;
   jclass cls = NULL;

   cls = env->FindClass("net/joshuad/test/Main");
   if(env->ExceptionCheck()) {  
      env->ExceptionDescribe();
      env->ExceptionClear();
   }

   if (cls != NULL) {
      main = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
   } else {
      printf("Unable to find the requested class\n");
   }

   if (main != NULL) {
      env->CallStaticVoidMethod( cls, main, " ");
   } else {
      printf("main method not found") ;
   }

   jvm->DestroyJavaVM();
   return 0;
}

【问题讨论】:

    标签: c windows dll path


    【解决方案1】:

    仅当您的程序编写在包含 jre 文件夹的同一目录中时,给定路径才有效。否则,您将必须指定完整位置,例如“C:\\jdk\\jrebin\server\\jvm.dll”

    【讨论】:

    • 是的,我的程序位于一个文件夹中,其中包含一个名为“jre”的子文件夹,其中包含整个 java 运行时环境。我正在用我的程序分发 JRE。
    • 我不太确定这个答案是怎么回事。
    【解决方案2】:

    我想通了。为了以这种方式链接到嵌入式 JRE,我们需要 link explicitly 而不是隐式链接,因此我们的程序在运行之前不会尝试链接,然后使用函数指针而不是函数调用来调用 JNI_CreateJavaVM直接。

    公平免责声明——我是一个糟糕的 C++ 程序员,虽然这可行,但我不知道它是否使用了良好的做法。使用风险自负。

    对于其他可能尝试这样做的人来说,这是一个可行的示例:

    #include <jni.h> 
    #include <windows.h>
    
    typedef UINT (CALLBACK* JVMDLLFunction)( JavaVM**, void**, JavaVMInitArgs * );
    
        int main() {        
            HINSTANCE jvmDLL = LoadLibrary(".\\jre\\bin\\server\\jvm.dll");
    
            if ( !jvmDLL ) {
                 printf("failed to find jvm.dll at specified location, exiting.\n");
                 return 1;
            }
    
            JVMDLLFunction createJavaVMFunction = (JVMDLLFunction)GetProcAddress(jvmDLL, "JNI_CreateJavaVM");
    
            if ( ! createJavaVMFunction ) {
                 printf("Failed to get pointer to JNI_CreateJavaVM function from jvm.dll, exiting\n");
                 return 1;
            } 
    
            JavaVM *jvm; 
            JNIEnv *env;
            JavaVMInitArgs vm_args; 
            JavaVMOption* options = new JavaVMOption[1];
    
            int index = 0;
            options[index].optionString = (char *)"-Djava.class.path=./main.jar";
    
            vm_args.version = JNI_VERSION_10;
            vm_args.nOptions = 1;
            vm_args.options = options;
            vm_args.ignoreUnrecognized = false;
    
            createJavaVMFunction( &jvm, (void**)&env, &vm_args );
    
            //JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
            delete options;
    
            jmethodID main = NULL;
            jclass cls = NULL;
    
            cls = env->FindClass("net/joshuad/test/Main");
            if(env->ExceptionCheck()) {  
              env->ExceptionDescribe();
              env->ExceptionClear();
            }
    
            if (cls != NULL) {
              main = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
            } else {
              printf("Unable to find the requested class\n");
            }
    
            if (main != NULL) {
              env->CallStaticVoidMethod( cls, main, " ");
            } else {
              printf("main method not found") ;
            }
    
            jvm->DestroyJavaVM();
            return 0;
        }
    

    【讨论】:

      猜你喜欢
      • 2010-09-17
      • 2015-10-19
      • 2022-08-03
      • 2016-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-29
      相关资源
      最近更新 更多