2010-07-13 72 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

相關問題