[C#/C++]C#調用非託管DLL的APIs

來源:互聯網
上載者:User
    上網baidu一下或google一下這個東東就有很多人在問這個問題,最近我也用到了這個,所以就留下來以備往後需要是可以尋找。我想通過這個來作為C#調用windows APIs的出發點,在以後的隨筆當中介紹一下我現階段用到的一些APIs或非託管類庫。在調用非託管DLL的APIs前,我們應該好好掌握一下DllImportAttribute,MSDN給出的定義為:可將該屬性應用於方法。DllImportAttribute 屬性提供對從非託管 DLL 匯出的函數進行調用所必需的資訊。作為最低要求,必須提供包含進入點的 DLL 的名稱。

1 [DllImport("KERNEL32.DLL", EntryPoint="MoveFileW",     SetLastError=true,

3 CharSet=CharSet.Unicode, ExactSpelling=true,

5 CallingConvention=CallingConvention.StdCall)]

7 public static extern bool MoveFile(String src, String dst);

    從上面的例子中我們可以看出,從Kernel32.dll中引入這個API,其中EntryPoint一看就知道是進入點,也就是DLL中的函數名稱。其實只要用過VC++的人都知道,Windows APIs中都提供兩個版本,一個是W,一個是A也就是Ansi和Unicode之分,現在一般都採用W,Unicode編程,但是.Net和win32互動的時候,預設是使用CharSet.Ansi來傳送。
在 DllImportAttribute.ExactSpelling 欄位為 true 時(它是 Visual Basic .NET 中的預設值),平台叫用將只搜尋您指定的名稱。例如,如果指定 MessageBox,則平台叫用將搜尋 MessageBox,如果它找不到完全相同的拼字則失敗。
當 ExactSpelling 欄位為 false(它是 C++ 託管擴充和 C# 中的預設值),平台叫用將首先搜尋未處理的別名 (MessageBox),如果沒有找到未處理的別名,則將搜尋已處理的名稱 (MessageBoxA)。

    由於很多參數和C#中有所區別,下面讓我們看看參數是怎麼個情況:

    extern “C” __declspec(dllexport)  int WINAPI sumAB(int a,int b)這個和C#中一樣是實值型別,a及b的變化不會對C#中的參數造成影響。通過DllImport表示為:1 [DllImport(“CppDll.dll")]
2 //返回個int 類型
3 public static extern int sumAB (int a1,int b1); 

    下面的是參考型別:也就是說a和b的變化直接影響到a1和b1的值。public static extern int sum (ref int a1,ref int b1);
//DLL中申明
extern “C” __declspec(dllexport)  int WINAPI sum(int *a,int *b) 

    同理我們可以得到一下幾種傳值方法:第一種參數的改變不影響C#中參數的變化,需要傳入char*類型。[DllImport(“CppDll.dll")]
//傳入值
public static extern int together (string  astr,string bstr);
//DLL中申明
extern “C” __declspec(dllexport)  int WINAPI together(char * stra,char * strb) 

    當我們需要從參數中傳出char*類型是,那我們就要用到StringBuilder了。1 // 傳出值
2 public static extern int getParameter (StringBuilder sb1, StringBuilder sb2);
3 //DLL中申明
4 extern “C” __declspec(dllexport)  int WINAPI getParameter(char * stra,char * strb) 

   
    接著我們先來看看結構的封送,這裡我們要看看StructLayoutAttribute這個標籤,通過它可以定義自己的格式化類型,在Managed 程式碼中,格式化類型是一個用StructLayoutAttribute說明的結構或類成員,通過它能夠保證其內部成員預期的布局資訊,他的成員說明如下:

     LayoutKind.Automatic
為了提高效率允許運行態對類型成員重新排序。
注意:永遠不要使用這個選項來調用非託管的動態連結程式庫函數。

     LayoutKind.Explicit
對每個域按照FieldOffset屬性對類型成員排序

     LayoutKind.Sequential
對出現在託管類型定義地方的非託管記憶體中的類型成員進行排序。

    我們可以通過GetSystemInfo來擷取系統的資訊,代碼如下:

 1 using System.Runtime.InteropServices;
 2 [StructLayout(LayoutKind.Sequential)]
 3     public struct SYSTEM_INFO {
 4     public uint dwOemId;
 5     public uint dwPageSize;
 6     public uint lpMinimumApplicationAddress;
 7     public uint lpMaximumApplicationAddress;
 8     public uint dwActiveProcessorMask;
 9     public uint dwNumberOfProcessors;
10     public uint dwProcessorType;
11     public uint dwAllocationGranularity;
12     public uint dwProcessorLevel;
13     public uint dwProcessorRevision;
14 }
15 //調用
16 [DllImport("kernel32")]
17 static extern void GetSystemInfo(ref SYSTEM_INFO pSI);
18 SYSTEM_INFO pSI = new SYSTEM_INFO();
19 GetSystemInfo(ref pSI);

    當我們遇到函數指標參數是我們就需要考慮是否要用到回呼函數,例如枚舉所有視窗。

BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARMAM IParam)

    我們可以通過建立一個代理,它帶有兩個參數hwnd和lparam,第一個參數是一個視窗控制代碼,第二個參數由應用程式定義,兩個參數均為整形。當這個回呼函數返回一個非零值時,標示執行成功,零則暗示失敗,這個例子總是返回True值,以便持續枚舉。
最後建立以代理對象(delegate),並把它作為一個參數傳遞給EnumWindows 函數,平台會自動地 把代理對象轉化成函數能夠識別的回調格式。

 1 using System;
 2 using System.Runtime.InteropServices;
 3 public delegate bool CallBack(int hwnd, int lParam);
 4 public class EnumReportApp {
 5 [DllImport("user32")]
 6 public static extern int EnumWindows(CallBack x, int y);
 7 public static void Main()
 8 {
 9 CallBack myCallBack = new CallBack(EnumReportApp.Report);
10 EnumWindows(myCallBack, 0);
11 }
12 public static bool Report(int hwnd, int lParam) {
13 Console.Write("視窗控制代碼為");
14 Console.WriteLine(hwnd);
15 return true;
16 }
17 }

    OK,如果熟悉了以上方方面面,基本上也能夠調用APIs了別忘了P/Invoke能夠幫上很大的忙,我們可以去wiki網站查詢我們所要的API:http://pinvoke.net。還需要說明的是很多例子等都來自MSDN和網上檢索得到的!!!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.