DllImport特性
首先我們來了解一下DllImport代碼特性,在進行互操作的時候,我們需要用DllImport來辨別該方法是非托管的代碼方法,在編譯器編譯的時候它能夠正确的認識出被該特性标記的是外來代碼段,是以能順利的通過編譯,當到達程式運作的時候,也能夠正确的認識出該代碼是引用非托管的代碼,這樣就讓我們的CLR去加載非托管DLL檔案,然後查找到入口點進行調用;我們拿上一篇文章中的示例來講吧;
[DllImport("Win32DLL.dll", EntryPoint = "add", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int AddNumber(int x, int y);
這段代碼申明了一個非托管代碼AddNumber方法,我們來看DllImport特性的這幾個屬性具體什麼意思;在DllImport構造函數裡面有一個dllname的參數,請看圖:
圖1:

我們可以看到注釋,這個構造函數的參數是非托管dll的名稱,也就是我們所要用到的導入方法的具體位置;上圖中的參數是 "Win32DLL.dll"字元串,也就是我們上篇文章中建立的非托管C++生成檔案,在後面有幾個相關屬性,我們也逐一來解釋;
DllImport特性中的EntryPoint可選屬性;
圖2:
DllImport特性中的CharSet可選屬性;
圖3:
CharSet屬性是用來确定在托管與非托管調用的過程中用什麼字元編碼來封送資料,因為我們的.NET平台是采用的Unicode編碼,而标準C++是采用的Ansi編碼,在我們了解了非托管代碼的編碼方式之後,我們就很确定用什麼編碼,那麼如果我們不清楚非托管代碼是用什麼語言編寫的或者不清楚它的編碼方式時,我們可以使用CharSet枚舉中的auto值,讓CLR自動為我們處理相關細節;
DllImport特性中的CallingConvention可選屬性;
CallingConvention屬性也是一個比較重要的屬性,在平台調用的過程中起到查找入口點的作用,在托管代碼進行非托管代碼入口點查找時,會通過CallingConvention中的值進行确認非托管入口點的調用約定,上篇文章中我們提到了調用約定的一些概念,
extern "C" _declspec(dllexport) int _stdcall add(int x,int y)
{
return x+y;
}
這段是非托管C++代碼,在這個方法前面有一個_stdcall的關鍵字,這個關鍵字的意思是說方法的調用約定,我們來看_stdcall調用的相關概念說明:函數的參數自右向左通過棧傳遞,被調用的函數在傳回前清理傳送參數的記憶體棧;意思是說,有被調用方來清理調用堆棧;
extern "C"關鍵代碼,是名稱修飾的意思,在編譯期間采用C編譯選項來編譯這個函數,由于C和C++是不同的語言,具體的文法也不相同,是以在C++中提供了選擇的餘地,讓我們可以選擇用什麼編譯方式來編譯方法,如果我們用"C"代碼修飾了之後,編譯器會通過區分不同的調用約定來重新命名方法的名稱;
摘:
__stdcall調用約定在輸出函數名前加上一個下劃線字首,後面加上一個"@"符号和其參數的位元組數,格式為_functionname@number,例如:function(int a, int b),其修飾名為:_function@8
__cdecl調用約定僅在輸出函數名前加上一個下劃線字首,格式為_functionname。
__fastcall調用約定在輸出函數名前加上一個"@"符号,後面也是一個"@"符号和其參數的位元組數,格式為@functionname@number。
(由于本人非C++出身是以未能總結出自己的一套了解思路,再此先用一下網摘的說明)