C#調用非託管代碼的方式主要有Com調用、DllImport方式調用、加載非託管動態連接庫、直接執行機器碼等方式。函數
如今介紹一下我本身經常使用的DllImport方式調用MSDN中提到的GetShortPathName方法;找到GetShortPathName的方法簽名,ui
DWORD GetShortPathName(LPCTSTR tpszLongPath,TPTSTR lpszShortPath,DWORD cchBuffer);code
非託管及託管數據類型對應關係:字符串
LPCTSTR String編譯器
LPTSTR StringBuilderio
DWORD int編譯
DllImport的導入規則:ast
一、方法名與Win API徹底同樣。若是在C#中調用時顯示徹底不一樣的方法名稱,則須要引入EntryPoint屬性,使用別名顯示。class
二、函數除須要DllImport類修飾符外,還須要聲明public static extern類型。變量
三、函數返回值和參數必須和調用的API的徹底同樣。
四、必須引入System.Runtime.InteropServices命名空間。
代碼:
using System.Runtime.InteropServices;
public class Test
{
[DllImport("kernel32.dll",CharSet=CharSet.Auto,EntryPoint="GetShort")]
public static extern int GetShortPathName(
[MarshalAs(UnmanagedType.LPTStr)] String path,
[MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath,
int shortPathLength);
}
代碼調用中kernel32.dll的路徑之因此沒寫是由於DllImport會按照如下三種順序查找Dll:
一、exe所在目錄;二、System32目錄;三、環境變量目錄。
MarshalAs爲可選類型,由於每一個數據類型都有默認的封送行爲,該屬性指示如何在託管代碼和非託管代碼之間的封送數據,可將該屬性用於參數、字段和返回值。大多數狀況下該屬性只是用UnmanagedType枚舉類型就能知足大多數非託管的數據類型,如默認狀況下字符會被看成BStr傳入到Dll中,可使用MarshalAs將字符串指定爲LPTStr、LPWStr或LPStr等。
DllImport可選屬性解釋
EntryPoint 可對方法採用不一樣的名稱,使用別名
CharSet 函數調用使用Unicode仍是Ansi
ExactSpelling False,表示讓編譯器本身選擇使用Unicode或Ansi
CallingConvetnion 它的參數指示入口點調用的約定;不指定默認爲CallingConvention.WinAPI
PreserveSig 指示方法簽名應當被保留仍是被轉換,當被轉換時它被轉換爲一個具備HRESULT返回值和該返回值的一個名爲retval的附加輸出參數的簽名,默認爲true。
SetLastError 指定是否保留上一次錯誤,默認爲false