首先,我知道直接比较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或其他功能?
答案 0 :(得分:5)
使用GetProcAddress的唯一真正优点是您可以手动卸载DLL以及调用函数,并且可以在运行时轻松更改命名。
但是,第二个选项为您提供了大量的好处。除了“更整洁”之外,它还为您处理大部分数据类型的编组 - 这对于某些API来说非常重要。
话虽这么说,如果你做的是你首先列出的方法,你应该确保卸载所有东西。现在,每次拨打Bar()时,你基本上都会泄漏地址......有关详细信息,请查看FreeLibrary。
答案 1 :(得分:4)
GetProcAddress
的最大优点可能是它允许您控制DLL的搜索路径。例如,您可以自动加载32位或64位版本的本机DLL。使用DllImportAttribute
时,这是不可能的。