2010-07-13 73 views
3

首先,我知道直接比较dllimport属性和getProcAddress函数是没有意义的。相反,我有兴趣比较两段代码,它们实现了基本相同的功能 - 通过导入具有dllimport属性的函数或getProcAddress函数来调用dll中的函数。具体来说,我正在编写一个C#应用程序,它在我编写的dll中使用了一些函数。起初,我访问我的DLL函数与下面的代码:dllimport和getProcAddress之间的区别

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或其他函数?

回答

4

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

但是,第二个选项为您提供了很多好处。除了“更整洁”之外,它还处理大部分数据类型的编组 - 这对于某些API非常重要。这就是说,如果你按照第一个方法列出的方法,那么你也应该确保卸载所有的东西。现在,每当你打电话给Bar()时,你基本上都在泄漏地址...详情请看FreeLibrary

+0

谢谢你的回答。在我的代码中,我实际上在构造函数中加载了库,在析构函数中释放了库,并将所有内容作为单例使用,因为我不知道是否会导致不止一次加载库。为了保证正确性,我编辑了我的帖子,同时释放图书馆。 – Boris 2010-07-13 23:52:28

+0

@Boris:'LoadLibrary'和'FreeLibrary'做引用计数,所以多次调用都可以正常工作。 – 2010-07-13 23:58:50

+0

你是什么意思的“泄漏地址”?该DLL只加载一次,内存中只存在该函数的一个副本,并且该代理被垃圾收集。 – 2010-07-14 00:00:31

2

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

+0

本:只是一个简单的 - 你可以通过使库位于一个单独的路径,并在运行时改变搜索路径来实现[DllImport]。 – 2010-07-13 23:37:19

+0

你的意思是搞乱了PATH环境变量?不建议。 http://blogs.msdn.com/b/oldnewthing/archive/2008/12/11/9193695.aspx – 2010-07-13 23:58:05

相关问题