2011年7月4日 星期一

將非 COM 元件的外部 DLL ,包入 .NET 開發的執行檔中 (PART 2)

接續上一篇文章的程式碼實作部份

假設某一個 DLL (AddNumber.dll)
提供一個功能叫做 Add2Number(Num1,Num2) as Integer
首先將這個 AddNumber.dll 加入資源檔中

然後新增一個 Class (clsTest.vb)內容如下,新增三個會用到的 API

    Declare Function LoadLibrary Lib "kernel32" (ByVal LibFilePath As String) As Integer
    Declare Function GetProcAddress Lib "kernel32" (ByVal ModuleHandle As Integer, ByVal ProcName As String) As Integer
    Declare Function FreeLibrary Lib "kernel32" (ByVal ModuleHandle As Integer) As Integer

先前提到要載入的 DLL 有個 Function 叫 Add2Number 所以也要加進來讓主程式呼叫用
  Delegate Function TestAdd2Number(ByVal Num1As Integer,ByVal Num1As Integer) As Integer
這裡使用委派 (Delegate) 的 Function Name 為了區別,我特地加了 Test 字樣

再來是主程式的部份
主程式裡要引用 System.Runtime.InteropServices ,以及剛才建立的 clsTest 檔案
  Imports System.Runtime.InteropServices
  Imports clsTest

在主程式的 Class下,順便把要用的變數設定好
Private _dllFuctionHandle As IntPtr
Private _loadDLLPath As String = "C:\TestAdd.DLL"   '解出的DLL要存放的路徑

程式執行時要先由資源檔中解出 DLL
My.Computer.FileSystem.WriteAllBytes(Me._loadDLLPath, My.Resources.AddNumberDll, False)
請注意上面的 AddNumberDll 是指在資源檔中的名稱

好了,DLL 檔解出來了再來是動態載入
Me._dllFuctionHandle = LoadLibrary(Me._loadDLLPath)

呼叫 API 載入 DLL 後,會傳回一個 Handle 碼,我們會利用這個 Handle 碼把 DLL 內的 Function 找出來。

Dim openMethodPointer As IntPtr  '利用 GetProcAddress 的 API 取得 DLL 的 Function Handle
Dim dllMethod As TestAdd2Number '指向委派的 Function Name


'利用 API 取得 DLL 的 Function
openMethodPointer = GetProcAddress(Me._dllFuctionHandle, "Add2Number") '這裡的 Add2Number 是 DLL 中實際可使用的 Function Name

取得了 Function Handle 後就要把它轉換成可用的 Type
dllMethod = CType(Marshal.GetDelegateForFunctionPointer(openMethodPointer, GetType(TestAdd2Number)), TestAdd2Number)

大功告成了。
最後就可以開始使用 AddNumber.dllAdd2Number這個 Function 囉~

Dim returnNumber As Integer
returnNumber = dllMethod(123,456)
回傳的結果就是兩數相加
returnNumber 的值就會等於 579

以上,看起來很煩瑣,其實一個一個操作下來並不難,
當然也可以把 Declare Delegate 都寫在同一個程式碼中,
就看程式怎麼應用了。

最後有個很重要的一點
就是使用完後請記得回收 DLL
   ''釋放 DLL
   ret = FreeLibrary(Me._dllFuctionHandle)
   ''刪除 DLL
   System.IO.File.Delete(Me._loadDLLPath)

沒有留言:

張貼留言