1,什麼是dll檔案?
DLL(Dynamic Link Library)檔案為動态連結庫檔案,又稱“應用程式拓展”,是軟體檔案類型。在Windows中,許多應用程式并不是一個完整的可執行檔案,它們被分割成一些相對獨立的動态連結庫,即DLL檔案,放置于系統中。當我們執行某一個程式時,相應的DLL檔案就會被調用。一個應用程式可使用多個DLL檔案,一個DLL檔案也可能被不同的應用程式使用,這樣的DLL檔案被稱為共享DLL檔案。
2,托管dll和非托管dll差別是什麼?
托管DLL就是能夠在公共語言運作庫(Common Language Runtime,簡稱CLR)中能夠直接引用的,并且擴充為“DLL”的檔案。具體所指就是封裝各種命名空間所在的DLL檔案,如System.dll等。非托管DLL就是平常所的動态連結庫等,其中就包括了封裝所有Windows API函數的DLL檔案。各種非托管DLL中的函數在公共語言運作庫中不能直接被調用,而需要經過.Net架構提供的“平台調用”服務後才可以。(簡而言之就是.net環境下生成的動态連結庫為托管dll,相反則為非托管dll)
3,托管dll和非托管dll如何使用?
托管dll在VS環境下使用相對容易,可以在項目名上右擊選擇添加應用的方式導入dll,本文這裡不作詳解。非托管dll的使用步驟及如下:
1,需要檢查使用的dll的目标平台(Any Cpu,x86,x64),在項目屬性生成頁籤中選擇與dll相對應的目标平台。因為托管dll是在.net的環境下生成的,轉換為機器語言後能夠自動識别目标平台即有架構支援解釋,而非托管不能夠自己識别需要人為的設定。
2,使用DllImport導入非托管dll。
DllImport會按照以下3種順序查找dll檔案:
1)、exe所在目錄;
2)、System32目錄(系統目錄);
3)、環境變量目錄。(即需要将dll及依賴檔案放到3個目錄中的任何一個目錄中)。
DllImport的導入規則:
1)、方法名與Win API完全一樣。如果在C#中調用時顯示完全不同的方法名稱,則需要引入EntryPoint屬性,使用别名顯示。
2)、函數除需要DllImport類修飾符外,還需要聲明public static extern類型。
3)、函數傳回值和參數必須和調用的API的完全一樣。
4)、必須引入System.Runtime.InteropServices命名空間。
DllImport的可選屬性參數說明:
EntryPoint 指定要調用的 DLL 入口點。
SetLastError 判斷在執行該方法時是否出錯(使用 Marshal.GetLastWin32Error API 函數來确定)。 C#中預設值為 false。
CharSet 控制名稱及函數中字元串參數的編碼方式。預設值為 CharSet.Ansi。
ExactSpelling 是否修改入口點以對應不同的字元編碼方式。
CallingConvention 指定用于傳遞方法參數的調用約定。預設值為 WinAPI。該值對應于基于32位Intel平台的 __stdcall。
BestFitMapping 是否啟用最佳映射功能,預設為 true。 最佳映射功能提供在沒有比對項時,自動提供比對的字元。 無法映射的字元通常轉換為預設的“?”。
PreserveSig 托管方法簽
名是否轉換成傳回 HRESULT,預設值為 true(不應轉換簽名)。 并且傳回值有一個附加的 [out, retval] 參數的非托管簽名。
ThrowOnUnmappableChar 控制對轉換為 ANSI '?' 字元的不可映射的 Unicode 字元引發異常。
4,c#與c++、c動态連結庫的參數如何對應?
C C# 備注
short int16 短整型
int int32 整型
long int64 長整型
& ref 取位址
* ref 指針
c#中修飾符ref、out的作用及功能
ref 要求參數在傳遞給函數前要初始化,out則不需要,常見于平台調用中。out和ref傳遞的都是引用而不是值,out側重于輸出使用之前不需指派而ref在使用之前需要指派,另外這兩個關鍵字可以變相實作使一個方法輸出多個值。ref可以把參數的數值傳遞進函數,但是out是要把參數清空,就是說你無法把一個數值從out傳遞進去的,out進去後,參數的數值為空,是以你必須初始化一次。這個就是兩個的差別,或者說就像有的網友說的,ref是有進有出,out是隻出不進。說明是引用的傳遞。
example:
//命名空間
using System.Runtime.InteropServices;
//導入非托管dll
//配置設定的庫處理和連接配接到數控指定的IP位址或主機名。
[DllImport("Fwlib64.dll", EntryPoint = "cnc_allclibhndl3", CallingConvention=CallingConvention.Cdecl)]
//short (const char *ipaddr, unsigned short port, long timeout, unsigned short *FlibHndl)
private static extern Int16 cnc_allclibhndl3(ref String ip, UInt16 port, Int64 timeout, ref UInt16 flibHndl);
(整理,源文章來源于網絡)