在C ++程序中指定路径

时间:2018-12-01 07:25:44

标签: c windows dll path

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

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

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

如果我将简单的可执行文件移到jre\bin\server所在的jvm.dll并尝试运行它,它将起作用。 所以我只需要告诉我的程序在其他特定位置搜索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;
}

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我知道了。为了以这种方式链接到嵌入式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;
    }