2

C#/.NET 3.5 アプリケーションを開発しています。C で記述されたレガシー dll、signals.dll を使用しています。P/Invoke を使用して .NET ラッパーから呼び出します。タイプ A とタイプ B の 2 種類の処理関数を呼び出しています。1 種類の処理のみを呼び出すと、すべて正常に動作します。A 処理と B 処理の呼び出しをインターリーブすると、データ結果が破損します。dll、signals.dll が C スタイルのグローバル変数を使用しており、データが破損していると思われます。

これを解決するために、ディスク上に dll の 2 つのコピー、signals.dll と signals2.dll を作成しました。次に、P/Invoke を使用して .NET ラッパーを変更し、タイプ A の処理を​​ 1 つの dll に、タイプ B の処理を​​別のインスタンスに指示しました。そして今、すべてが正常に動作します。

次に、フォーラムで同様の問題とそこでの解決策を見ました。(グローバル データを使用してプラグイン DLL の複数のインスタンスをサポートする)。基本的に、その提案されたソリューションはコードから動的に配置され、(必要に応じて) ディスク上に .dll の新しいインスタンスを作成し、それをロードしてそこから関数を呼び出します。コードの主要部分は次のようになります。

private IntPtr dllHandle;
string myDllPath = Path.Combine(dllDir, String.Format("mylib-{0}.dll", GetHashCode()));
        File.Copy(origDllPath, myDllPath);
        dllPath = myDllPath;
        dllHandle = LoadLibrary(dllPath);
        _getVersion = GetProcEntryDelegate<_getVersionDelegate>(dllHandle, "GetVersion");

    private delegate int _getVersionDelegate();
    private readonly _getVersionDelegate _getVersion;

public int GetVersion()
    {
        return _getVersion();
    }

private static D GetProcEntryDelegate<D>(IntPtr hModule, string name)
        where D: class
    {
        IntPtr addr = _getProcAddress(hModule, name);
        if (addr == IntPtr.Zero)
            throw new Win32Exception();
        return Marshal.GetDelegateForFunctionPointer(addr, typeof(D)) as D;
    }

私の頭に浮かぶのは、上記のコードを変更して、ディスクではなくメモリー内にdllのコピーを作成し、そこからロードすることは可能でしょうか。LoadLibrary からではなく、メモリから値を取得するには、IntPtr dllHandle を騙す必要があると思います。どうやってするか?

4

2 に答える 2

1

LoadLibraryLoadLibraryExの両方にファイル パスが必要です。メモリ マッピングなどを含む、カスタムの読み込み手順が必要になります。手順を説明しているブログ投稿 (「メモリから DLL を読み込む」)と、それに対応する GitHub プロジェクトを見つけました。メモリーモジュール.

于 2013-04-14T08:29:10.067 に答える