C ++ / CLI LoadLibrary在将System :: String转换为LPCWSTR和const char时失败*

时间:2012-04-05 01:33:18

标签: visual-c++ c++-cli

尝试传入用户提供的字符串,该字符串具有jvm.dll的路径,但除非我使用以下代码进行硬编码,否则它不会加载库:

#define RUNTIME_DLL _T("C:\\Program Files\\Java\\jre7\\bin\\Server\\jvm.dll")

如果我尝试这个,它会编译但失败:

HINSTANCE handle = LoadLibrary((const char*)Marshal::StringToHGlobalAnsi(string).ToPointer());

“string”var具有_T()具有但仍然失败的精确复制和粘贴路径。不是C / C ++的专家,所以我不确定_T()是什么让它起作用。

更新

试过这个:

// System::String always stored as Unicode, get a Unicode pointer with no conversion necessary
        pin_ptr<const WCHAR> lib_name = PtrToStringChars(string);
        // Always use the Unicode version of LoadLibrary
        HINSTANCE handle = LoadLibraryW(lib_name);

仍然不会加载jvm.dll文件。如果我这样做,它只会加载它:

#define RUNTIME_DLL _T("C:\\Program Files\\Java\\jre7\\bin\\Server\\jvm.dll")

        // System::String always stored as Unicode, get a Unicode pointer with no conversion necessary
        pin_ptr<const WCHAR> lib_name = PtrToStringChars(RUNTIME_DLL);
        // Always use the Unicode version of LoadLibrary
        HINSTANCE handle = LoadLibraryW(lib_name);

也尝试过这个:

        // System::String always stored as Unicode
        marshal_context^ ctx = gcnew marshal_context();
        pin_ptr<const WCHAR> lib_name = PtrToStringChars(jvmDllPath);           
        //const wchar_t * lib_name = ctx->marshal_as<const wchar_t*, System::String^>(jvmDllPath);
        printf("JVM Path: %s", lib_name);
        // Always use the Unicode version of LoadLibrary
        handle = LoadLibraryW(lib_name);            

        if( handle == 0) {
            printf("Failed to load jvm dll \n");
            //printf(ErrorExit((LPTSTR)(const char*)"Initialize"));
                            // this is the part that will work
            System::String^ string = gcnew System::String("C:\\Program Files\\Java\\jre7\\bin\\Server\\jvm.dll");
            pin_ptr<const WCHAR> lib_name = PtrToStringChars(string);
            handle = LoadLibraryW(lib_name);
        }
        delete ctx;  // do this for now to not create memory leaks

C ++ / CLI方法签名是:

void Initialize(String^ jvmDllPath)

正文基本上是上面的代码

使用字符串参数调用此代码的C#代码为:

obj.Initialize("c:\\program files\\java\\jdk7\\jre\\bin\\server\\jvm.dll");

根据Ben的建议在这里提供答案,以便人们/新手和临时c / c ++ / cli程序员能够快速找到答案,以避免我经历过的事情:

    const char * CliToNativeString(String^ cliString){
        const char * converted;
        converted = (gcnew marshal_context())->marshal_as<const char *>( cliString );           
        return converted;
    }

    String^ NativeToCliString(const char * nString){
        String^ converted = gcnew String("");
        if(nString != NULL)
            converted = (gcnew marshal_context())->marshal_as<String^>(nString); 
        return converted;
    }

1 个答案:

答案 0 :(得分:3)

有更好的方法可以从System::String^获取C风格的字符串。查看VC ++提供的marshal_asmarshal_context模板。

这里您当前的问题是您正在编译Unicode,因此LoadLibrary需要unicode字符串,但StringToHGlobalAnsi不返回unicode字符串。没有多少指针转换会改变指向的字符串的编码。

你也有内存泄漏。

请改为尝试:

#include <vcclr.h>

// System::String always stored as Unicode, get a Unicode pointer with no conversion necessary
pin_ptr<const WCHAR> lib_name = PtrToStringChars(string);
// Always use the Unicode version of LoadLibrary
HINSTANCE handle = LoadLibraryW(lib_name);

如果这样做而且上面没有,那么从C#发送的字符串有问题:

System::String^ string = gcnew System::String(L"C:\\Program Files\\Java\\jre7\\bin\\Server\\jvm.dll");
pin_ptr<const WCHAR> lib_name = PtrToStringChars(string);
HINSTANCE handle = LoadLibraryW(lib_name);