1

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

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

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

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

“字符串” 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)

body基本上就是上面的代码

使用字符串参数调用 this 的 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;
    }
4

1 回答 1

3

有更好的方法可以从System::String^. 查看VC++ 提供的marshal_as和模板。marshal_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);
于 2012-04-05T02:24:28.180 回答