5

まず、dllimport 属性と getProcAddress 関数を直接比較しても意味がないことはわかっています。むしろ、dllimport 属性または getProcAddress 関数を使用して関数をインポートすることにより、基本的に同じこと (dll で関数を呼び出す) を実現する 2 つのコードを比較することに興味があります。具体的には、私が作成した dll の関数を使用する C# アプリケーションを作成しています。最初に、次のコードで dll 関数にアクセスしました。

class DllAccess
{
    [DllImport("kernel32.dll", SetLastError = true)]
    private extern IntPtr LoadLibrary(String DllName);

    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate Bool BarType(Byte arg); // return value indicates whether function call went well or not.

    Bool Bar(Byte arg)
    {
        Bool ok = false;
        IntPtr pDll= LoadLibrary("foo.dll");
        if (pDll != IntPtr.Zero)
        {
            IntPtr pfunc = GetProcAddress(pDll, "bar");
            if (pFunc != IntPtr.Zero)
            {
                BarType bar = (BarType)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(BarType));
                ok = bar(arg);
            }
            FreeLibrary(pDll);
        }
        return ok;
    }
}

ただし、dll 呼び出し中に設定されていた場合は、後で lastError 値を取得する必要があったため、コードを次のように変更しました。

class DllAccess
{
    [DllImport("foo.dll", EntryPoint = "bar", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private extern Bool DllBar(Byte arg); // return value indicates whether function call went well or not.

    Bool Bar(Byte arg)
    {
        return DllBar(arg);
    }
}

もちろん、これははるかに整頓されており、前述のように、lastError コードを設定します。明らかに、私の最初のコードでは、実行時に dll と関数呼び出しを変更できる可能性がありますが、現時点ではこれは必要ありません。したがって、私の質問は次のとおりです。別のdllまたは別の関数を使用しないことが確実である場合、最初の定式化を使用する理由はありますか?

4

2 に答える 2

5

GetProcAddress を使用する唯一の本当の利点は、DLL を手動でアンロードしたり、関数を呼び出したりできることと、実行時に名前を簡単に変更できることです。

ただし、2 番目のオプションには、膨大な数の利点があります。「より整頓されている」ことに加えて、データ型のマーシャリングの多くを処理します。これは、特定の API で非常に重要になります。

そうは言っても、最初にリストした方法を実行する場合は、すべてをアンロードすることも確認する必要があります。現在、基本的に Bar() を呼び出すたびにアドレスをリークしています... 詳細については、FreeLibraryを参照してください。

于 2010-07-13T23:32:39.343 に答える
4

おそらく最大の利点はGetProcAddress、DLL の検索パスを制御できることです。たとえば、ネイティブ DLL の 32 ビット バージョンまたは 64 ビット バージョンを自動的にロードできます。ではDllImportAttribute、これは不可能です。

于 2010-07-13T23:36:27.963 に答える