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

「文字列」変数には、_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");

ここでベンの提案から回答を提供して、人々/初心者および一時的な 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

から C スタイルの文字列を取得するためのより良い方法がありますSystem::String^。VC++ で提供されるmarshal_asとテンプレートを見てください。marshal_context

ここでの差し迫った問題は、Unicode 用にコンパイルしているためLoadLibrary、Unicode 文字列が必要ですが、Unicode 文字列をStringToHGlobalAnsi返さないことです。ポインターをいくらキャストしても、指している文字列のエンコードが変更されることはありません。

メモリリークもあります。

代わりにこれを試してください:

#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 に答える