dllimport和getProcAddress之间的区别

时间:2010-07-13 23:27:29

标签: c# pinvoke dllimport getprocaddress

首先,我知道直接比较dllimport属性和getProcAddress函数是没有意义的。相反,我感兴趣的是比较两段代码,通过使用dllimport属性或使用getProcAddress函数导入函数,实现基本相同的东西 - 在dll中调用函数。具体来说,我正在编写一个C#应用程序,它在我编写的dll中使用了一些函数。起初我使用以下代码访问了我的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;
    }
}

但是,我后来需要获取lastError值,如果它是在dll调用期间设置的,那么我将代码更改为:

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或其他功能?

2 个答案:

答案 0 :(得分:5)

使用GetProcAddress的唯一真正优点是您可以手动卸载DLL以及调用函数,并且可以在运行时轻松更改命名。

但是,第二个选项为您提供了大量的好处。除了“更整洁”之外,它还为您处理大部分数据类型的编组 - 这对于某些API来说非常重要。

话虽这么说,如果你做的是你首先列出的方法,你应该确保卸载所有东西。现在,每次拨打Bar()时,你基本上都会泄漏地址......有关详细信息,请查看FreeLibrary

答案 1 :(得分:4)

GetProcAddress的最大优点可能是它允许您控制DLL的搜索路径。例如,您可以自动加载32位或64位版本的本机DLL。使用DllImportAttribute时,这是不可能的。