C++/CLI LoadLibrary在转换系统:::字符串到LPCWSTR和const char *上失败

时间:2022-09-01 11:31:43

Trying to pass in a user supplied string which has a path to the jvm.dll but it doesn't load the library unless I hard code with the following:

试图传递一个用户提供的字符串,该字符串有通向jvm的路径。dll,但它没有加载库,除非我用下面的硬编码:

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

It compiles but fails if I try this:

如果我这样做,它会编译但是失败:

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

The "string" var has the exact copy and pasted path that _T() has but still fails. Not an expert in C/C++ so I'm not sure what _T() gets it to work.

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

Update:

更新:

Tried this:

尝试:

// 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);

And still it won't load the jvm.dll file. It will only load it if I do this:

它仍然不会加载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);

Tried this as well:

尝试这个:

        // 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

The C++/CLI method signature is:

c++ /CLI方法签名为:

void Initialize(String^ jvmDllPath)

The body is basically the code above

主体基本上就是上面的代码

The C# code that calls into this with a string parameter is this:

使用字符串参数调用c#的代码是:

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

Providing answer here from Ben's suggestion so people/newbs and temporary c/c++/cli coders can find a quick answer to avoid what I went through:

从Ben的建议中提供答案,所以人们/newbs和临时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 个解决方案

#1


3  

There are better ways for getting a C-style string from a System::String^. Have a look at the marshal_as and marshal_context templates supplied with VC++.

有更好的方式获得c风格的字符串从一个系统:^:字符串。看看vc++提供的marshal_as和marshal_context模板。

Your immediate problem here is that you are compiling for Unicode, so LoadLibrary requires a unicode string, but StringToHGlobalAnsi does not return a unicode string. No amount of pointer casting will change the encoding of the string pointed to.

这里的直接问题是要编译Unicode,因此LoadLibrary需要一个Unicode字符串,但是StringToHGlobalAnsi不返回Unicode字符串。任何数量的指针转换都不会改变指向的字符串的编码。

You also have a memory leak.

您还存在内存泄漏。

Try this instead:

试试这个:

#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);

If this works and the above doesn't, then something is wrong with the string sent from C#:

如果这是可行的,上面没有,那么从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);

#1


3  

There are better ways for getting a C-style string from a System::String^. Have a look at the marshal_as and marshal_context templates supplied with VC++.

有更好的方式获得c风格的字符串从一个系统:^:字符串。看看vc++提供的marshal_as和marshal_context模板。

Your immediate problem here is that you are compiling for Unicode, so LoadLibrary requires a unicode string, but StringToHGlobalAnsi does not return a unicode string. No amount of pointer casting will change the encoding of the string pointed to.

这里的直接问题是要编译Unicode,因此LoadLibrary需要一个Unicode字符串,但是StringToHGlobalAnsi不返回Unicode字符串。任何数量的指针转换都不会改变指向的字符串的编码。

You also have a memory leak.

您还存在内存泄漏。

Try this instead:

试试这个:

#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);

If this works and the above doesn't, then something is wrong with the string sent from C#:

如果这是可行的,上面没有,那么从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);