0

私の問題とプロセスを完全に説明します。私は他のゲームのエディターを作成していましたが、通信している C 言語で記述されたラッパー DLL が 1 つあります。

DllImport最初は、DLL から関数を呼び出すメソッドのリストがありました。最初のメソッドはCSharp_new_CEditorInterfaceIntPtr. 次に、グラフィックスを描画するウィンドウ コントロールへのハンドルCSharp_CEditorInterface_CreateAppを取得します。ulong最後に and を呼び出す必要がCSharp_CEditorInterface_CloseAppありCSharp_delete_CEditorInterfaceます。これらのメソッドは、HandleRefから返された with ポインタを受け取りますCSharp_new_CEditorInterface

ただし、メソッドの作成と削除を複数回呼び出す必要がありCSharp_CEditorInterface_CreateApp、2 回目に呼び出すと、 がスローされましたSystem.AccessViolationException。そこで、LoadLibrary と FreeLibrary を使用して DLL を動的にロードおよびアンロードすることにしました。リフレクションを使用してすべての p/invoke メソッドを参照し、デリゲート、読み取り専用フィールド、GetProcAddress で構成されるコードを生成するアプリケーションを作成しました。しかし、私が知ったように、エントリ ポイントは部分的なものに過ぎませんでした。CSharp_new_CEditorInterfaceでした_CSharp_new_CEditorInterface@0。DLL エクスポート ビューアーを使用して、すべての完全な関数名を保存し、その中で検索しました。コンストラクターでは、適切な関数を呼び出しLoadLibraryてロードします。にDispose、ありましたFreeLibrary

このソリューションは正常に機能し、関数は OK と呼ばれていましたが、文字列を返す一部の関数が をスローしていることに気付きAccessViolationExceptionました。メソッドを使用する場合、それらは正常に機能しDllImportます。また、静的クラスから任意の関数を呼び出して別のモジュールをロードすると、問題のある関数を呼び出しても問題なく、適切な値が返されることも発見しました。ただし、DLL を動的にアンロードして再ロードした後、再び動作せず、どの例外がスローされたかを推測します。

次に、どの関数をどの順序で呼び出すか:

--When initializing--
LoadLibrary(string)  (winapi)
--bunch of GetProcAddress, Marshal.GetDelegateForFunctionPointer--
new_CEditorInterface()  (from DLL)
CreateApp(HandleRef, ulong)  (from DLL)

--When closing in Dispose--
CloseApp(HandleRef)  (from DLL)
delete_CEditorInterface(HandleRef)  (from DLL)
FreeLibrary(IntPtr)  (winapi)

DLL は、一度に複数ロードされるように作成されていないことに注意してください。

誰か助けてくれませんか?

4

1 に答える 1

0

これを試してくださいこれがあなたに役立つことを願っています

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool FreeLibrary(IntPtr hModule);

//Load
IntPtr Handle = LoadLibrary(fileName);
if (Handle == IntPtr.Zero)
{
     int errorCode = Marshal.GetLastWin32Error();
     throw new Exception(string.Format("Failed to load library (ErrorCode: {0})",errorCode));
}

//Free
if(Handle != IntPtr.Zero)
        FreeLibrary(Handle);

最初に関数を呼び出したい場合は、この関数に一致する委任を作成してから WinApi GetProcAddress を使用する必要があります

[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); 


IntPtr funcaddr = GetProcAddress(Handle,functionName);
YourFunctionDelegate function = Marshal.GetDelegateForFunctionPointer(funcaddr,typeof(YourFunctionDelegate )) as YourFunctionDelegate ;
function.Invoke(pass here your parameters);
于 2012-08-13T11:04:31.653 に答える