Visual c++ C++/CLI LoadLibrary无法将System::String转换为LPCWSTR和const char*

Visual c++ C++/CLI LoadLibrary无法将System::String转换为LPCWSTR和const char*,visual-c++,c++-cli,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());

试图传入一个用户提供的字符串,该字符串具有到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”变量具有与_T()完全相同的复制和粘贴路径,但仍然失败。我不是C/C++方面的专家,所以我不确定是什么让它工作

更新:

        // 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
我试过这个:

// 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#代码如下:

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;
    }
const char*CliToNativeString(String^cliString){
const char*已转换;
转换=(gcnew marshal_context())->marshal_as(cliString);
转换收益;
}
字符串^NativeToCliString(常量字符*nString){
字符串^converted=gcnew字符串(“”);
如果(nString!=NULL)
转换=(gcnew marshal_context())->marshal_as(nString);
转换收益;
}

系统::string^
获取C样式字符串有更好的方法。查看VC++提供的
marshal_as
marshal_上下文
模板

这里的直接问题是您正在编译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);
#包括
//字符串始终存储为Unicode,无需转换即可获取Unicode指针
pin_ptr lib_name=PtrToStringChars(字符串);
//始终使用Unicode版本的LoadLibrary
HINSTANCE handle=LoadLibraryW(库名称);
如果这样做有效,而上述方法无效,那么从C#发送的字符串有问题:

System::String^String=gcnew System::String(L“C:\\Program Files\\Java\\jre7\\bin\\Server\\jvm.dll”);
pin_ptr lib_name=PtrToStringChars(字符串);
HINSTANCE handle=LoadLibraryW(库名称);

我还将(const char*)强制转换替换为(LPCWSTR),它可以编译,但仍然失败。。。。非常奇怪。是的,强制转换将迫使您的代码编译。这并不意味着它是正确的,甚至要求它有任何意义。如果您编写的代码不起作用,请从消除所有强制转换开始,并遵循编译器发出的错误诊断。我知道,但由于需要使用C++/CLI强制转换,因此并非如此。不过谢谢。不,没有规定C++/CLI需要强制转换。强制转换唯一“必需”的是屏蔽bug。我必须强制转换为字符串类型的变量^。基本上,这是托管包装器,由C#程序调用/使用/调用,该程序将类型System::String传递给C++/CLI包装器。然后,我必须将其转换为C样式的字符串,以便LoadLibrary()工作。如果我弄错了,我会很感激你的指点(没有双关语)。谢谢你的帮助尝试了你的方法,它也有同样的问题。我还尝试了更新帖子中的方法。非常奇怪。@bbqchickenrobot:你还有哪些问题?是编译错误(显示消息)还是运行时错误?
string
的值是多少?顺便说一句,
\u T
根据编译设置生成ANSI字符串或Unicode字符串。由于您是为Unicode编译的,
L“jvm.dll”
会给您同样的效果。实际上字符串中没有任何双反斜杠,对吧,只有在生成字符串的代码中才有?运行时错误。。。LoadLibrary()返回NULL。但是代码运行和编译时没有问题。我用#define RUNTIME(定义运行时)DLL替换它运行正常。。。并实际加载jvm.dll文件,程序运行正常。是的,我没有任何双反斜杠-已验证在调试期间变量中是否显示为c:\program files\…\jvm.dll。@bbqchickenrobot:尝试此版本(暂时出错,现在应该可以了)。
    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;
    }
#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);
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);