2017-06-21 290 views
0

我有一个由Jet excelsior生成的.dll,我试图从他们生成的调用dll中提取类。我正在按照他们原来在c中完成的示例脚本。尽管经过数小时的研究和排除故障,我无法使LoadLibrary调用开始工作。我正在运行Visual Studio 2017社区做一个空白的C++项目。这里是我的调用和调试信息的一小部分,我已经能够得到。任何解决方案或调试的建议是值得欢迎的,因为我越来越绝望了,还对我的C++使用任何技巧是值得欢迎的,因为我还是个新手:C++ LoadLibrary()导致程序退出

1. HINSTANCE test = LoadLibrary(L"C:\\Full Path\\myDll.dll"); 
2. //Code exits before reaching this point. 
3. int er = (int)GetLastError(); 

是的,我已经试过我的DLL移动到我的项目目录,只是调用文件名称。 不幸的是,我看不到getlasterror返回的内容,因为代码崩溃。 调试时,在执行第1行之前。其扩展信息是:
Name: test Value: 0xcccccccc{unused=???} unused <Unable to read memory>
我认为这是无关紧要的,因为它没有实际执行?
以下是完整的代码,如果它正好是相关的(它在底部未能在年初的main():

#include "stdafx.h" 
#include <string> 
#include <windows.h> 
#include <iostream> 
#include <C:\Program Files (x86)\Java\jdk1.8.0_131\include\jni.h> 

HINSTANCE loadDll(LPCWSTR name) 
{ 
    HINSTANCE hDll = LoadLibrary(name); 
    int thing = (int)GetLastError(); 
    if (!hDll) { 
     thing = (int)GetLastError(); 
     printf("Unable to load %s\n", name); 
     exit(1); 
    } 

    printf("%s loaded\n", name); 

    return hDll; 
} 

typedef jint(JNICALL * JNI_GetDefaultJavaVMInitArgs_func) (void *args); 
typedef jint(JNICALL * JNI_CreateJavaVM_func) (JavaVM **pvm, void **penv, void *args); 

/* 
* Initialize JET run-time. 
*/ 
void initJavaRT(HINSTANCE myDllHandle, JavaVM** pjvm, JNIEnv** penv) 
{ 
    JavaVMInitArgs args; 
    JNI_GetDefaultJavaVMInitArgs_func JNI_Init_Args = (jint(JNICALL *) (void *args)) GetProcAddress(myDllHandle, "JNI_GetDefaultJavaVMInitArgs"); 
    JNI_CreateJavaVM_func JNI_Create_VM = (jint(JNICALL *) (JavaVM **pvm, void **penv, void *args)) GetProcAddress(myDllHandle, "JNI_CreateJavaVM"); 

    if (!JNI_Init_Args) { 
     std::cerr << "!JNI_Init_Args\n"; 
     printf("%s doesn't contain public JNI_GetDefaultJavaVMInitArgs\n", dllName); 
     exit(1); 
    } 

    if (!JNI_Create_VM) { 
     printf("%s doesn't contain public JNI_CreateJavaVM\n", dllName); 
     exit(1); 
    } 

    memset(&args, 0, sizeof(args)); 

    /*args.version = JNI_VERSION_1_2; 
    if (JNI_GetDefaultJavaVMInitArgs_func(&args) != JNI_OK) { 
     printf("JNI_GetDefaultJavaVMInitArgs() failed with result %d\n", JNI_GetDefaultJavaVMInitArgs_func(&args)); 
     exit(1); 
    }*/ 

    /* 
    * NOTE: no JVM is actually created 
    * this call to JNI_CreateJavaVM is intended for JET RT initialization 
    */ 
    /*if (JNI_CreateJavaVM_func(pjvm, (void **)penv, &args) != JNI_OK) { 
     printf("JNI_CreateJavaVM() failed with result %d\n", JNI_CreateJavaVM_func(pjvm, (void **)penv, &args)); 
     exit(1); 
    }*/ 

    printf("JET RT initialized\n"); 
    fflush(stdout); 
} 


/* 
* Look for class. 
*/ 
jclass lookForClass(JNIEnv* env, char* name) 
{ 
    jclass clazz = env->FindClass(name); 

    if (!clazz) { 
     printf("Unable to find class %s\n", name); 
     exit(1); 
    } 

    printf("Class %s found\n", name); 
    fflush(stdout); 

    return clazz; 
} 


/* 
* Create an object and invoke the "ifoo" instance method 
*/ 
void invokeInstanceMethod(JNIEnv* env, jclass myClassInDll) 
{ 
    jmethodID MID_init, MID_ifoo; 
    jobject obj; 

    MID_init = env->GetMethodID(myClassInDll, "<init>", "()V"); 
    if (!MID_init) { 
     printf("Error: MyClassInDll.<init>() not found\n"); 
     return; 
    } 

    obj = env->NewObject(myClassInDll, MID_init); 
    if (!obj) { 
     printf("Error: failed to allocate an object\n"); 
     return; 
    } 

    MID_ifoo = env->GetMethodID(myClassInDll, "ifoo", "()V"); 

    if (!MID_ifoo) { 
     printf("Error: MyClassInDll.ifoo() not found\n"); 
     return; 
    } 

    env->CallVoidMethod(obj, MID_ifoo); 
} 



/* 
* Invoke the "foo" static method 
*/ 
void invokeStaticMethod(JNIEnv* env, jclass myClassInDll) 
{ 
    jmethodID MID_foo; 

    MID_foo = env->GetStaticMethodID(myClassInDll, "parse", "()V"); 
    if (!MID_foo) { 
     printf("\nError: MyClassInDll.foo() not found\n"); 
     return; 
    } 

    env->CallStaticVoidMethod(myClassInDll, MID_foo); 
} 


void finalizeJavaRT(JavaVM* jvm) 
{ 
    jvm->DestroyJavaVM(); 
} 


int main() 
{ 
    //Actually just trouble shooting code, not used in full program 
    HINSTANCE test = LoadLibrary(L"C:\\Full Path\\stgNativeProject.dll"); 
    int er = (int)GetLastError(); 

    //Actual program code 
    HINSTANCE myDllHandle; 
    JNIEnv *env; 
    JavaVM *jvm; 
    jclass myClassInDll; 

    /* 
    * First of all, load required component. 
    * By the time of JET initialization, all components should be loaded. 
    */ 
    std::cerr << dllName << "\n"; 
    myDllHandle = loadDll(dllName); 

    /* 
    * Initialize JET run-time. 
    * The handle of loaded component is used to retrieve Invocation API. 
    */ 
    initJavaRT(myDllHandle, &jvm, &env); 

    /* 
    * Look for class. 
    */ 
    myClassInDll = lookForClass(env, "MyClassInDll"); 

    /* 
    * Create an object and invoke instance method. 
    */ 
    invokeInstanceMethod(env, myClassInDll); 

    /* 
    * Invoke static method. 
    */ 
    invokeStaticMethod(env, myClassInDll); 

    /* 
    * Finalize JET run-time. 
    */ 
    finalizeJavaRT(jvm); 

    return 0; 
} 
+0

如果你打算这么快就downvote,至少给我一个改进p的方法租约和谢谢。 –

+0

0xcccccccc =未初始化的堆栈内存:https://stackoverflow.com/a/127404/487892 – drescherjm

+0

LoadLibrary是否应该在被调用时处理?认为这只是因为它还没有被实际执行 –

回答

0

我的问题的解决方法比较简单,我测试的一个工具叫喷气机。 Excelsior将预编译我的java代码以供本地使用。该实用程序创建了一个用于C++或c项目的.dll。我遇到的问题是调用dll需要与Jet运行时一起打包。检查文档here。如果你已经下载Jet,Jet样本调用dlls/cmain将会对你最有帮助。