C#通過p/invoke調用C++ DLL

來源:互聯網
上載者:User

轉自:http://hacker.cnblogs.com/archive/2004/08/12/32563.aspx

1, PInvoke什麼意思? Platform Invocation Services

2, 幹什麼用?  匯入外部函數?什麼是外部函數,就是不屬於.Net託管的函數。

3,如何用?看下面的例子。用[DllImport(dllname)]來實現,但是首先要把System.Runtiime.InteropServices using進來。但是不using也行,就要敲全稱,隨你便了。

[DllImport("user32.dll")] 
         static extern int MessageBoxA(int hWnd,

                                          string msg,

                                          string caption,

                                          int type );

         private void button1_Click(object sender, System.EventArgs e)

         {

              MessageBoxA( 0, "Msg:hello", "Caption:Hello",0 );

         }

4,萬一我的程式中已經有了一個函數叫MessageBoxA怎麼辦?這時候,可以使用EntryPoint來幫忙,下面的例子中,你把自己的函數定義為MyMsg.

[DllImport("user32.dll",EntryPoint="MessageBoxA")]

         static extern int MyMsg(int hWnd,

                                          string msg,

                                          string caption,

                                          int type );

         private void button1_Click(object sender, System.EventArgs e)

         {

              MyMsg( 0, "Msg:hello", "Caption:Hello",0 );

         }

5,charset如何使用?****A的是Ansi編碼,****W的是unicode編碼,如何使用charset,看你的函數調用而定。2K以後都用unicode了,前面的9x都是ansi編碼,但是這是預設的,微軟給9x打布丁支援unicode不算。

API有兩個版本: A(ASNI)版本和W(Unicode)版本. A版本調用時候會用ANSI來封送字串,一般是win95/98上。W版本用Unicode來封送,在NT,2K和XP上。

.Net和win32互動的時候,預設是使用CharSet.Ansi來傳送。

在 DllImportAttribute.ExactSpelling 欄位為 true 時(它是 Visual Basic .NET 中的預設值),平台叫用將只搜尋您指定的名稱。例如,如果指定 MessageBox,則平台叫用將搜尋 MessageBox,如果它找不到完全相同的拼字則失敗。

當 ExactSpelling 欄位為 false(它是 C++ 託管擴充和 C# 中的預設值),平台叫用將首先搜尋未處理的別名
(MessageBox),如果沒有找到未處理的別名,則將搜尋已處理的名稱 (MessageBoxA)。請注意,ANSI 名稱匹配行為與
Unicode 名稱匹配行為不同。       

 //CharSet.Ansi will call MessageBoxA

         //CharSet.Unicode will call MessageBoxW

 

         [DllImport("user32.dll",EntryPoint="MessageBox",CharSet=CharSet.Ansi)]

         static extern int MyMsg(int hWnd,

                                          string msg,

                                          string caption,

                                          int type );

         private void button1_Click(object sender, System.EventArgs e)

         {

              MyMsg( 0, "Msg:hello", "Caption:Hello",0 );

         }

6,Dll裡面的callback函數如何??看下面這個例子:

delegate bool CallBackDef( int hWnd, int lParm );

 

         [DllImport("user32.dll")]

              static extern int GetWindowText( int hWnd,

                                                   StringBuilder text,

                                                   int count );

         [DllImport("user32.dll")]

              static extern int EnumWindows(CallBackDef callback, int lParam );

 

         static bool PrintWindow(int hWnd, int lParm )

         {

              StringBuilder text = new StringBuilder(255);

              GetWindowText( hWnd, text, 255 );

              Console.WriteLine( text.ToString() );

 

              return true;

         }

 

         private void button1_Click(object sender, System.EventArgs e)

         {

              CallBackDef callBack = new CallBackDef( PrintWindow );

              EnumWindows( callBack, 0 );

         }

7,MarshalAs如何用,什麼時候用?
在MessageBox傳遞string去Dll的時,C#編譯器知道Win32LPSTR等價與一個C#字串。但是如果想覆蓋預設.Net行為, 這時候就需要MarshallAs

[DllImport("user32.dll", CharSet=CharSet.Unicode )]

              static extern int MessageBox( int hWnd,

                                               [MarshalAs(UnmanagedType.LPWStr)]

                                               string msg,

                                               [MarshalAs(UnmanagedType.LPWStr)]

                                               string caption,

                                               int type);

8,我怎麼知道要調用的函數在那個dll了?
這個問題我不會比你更清楚,特殊的函數應該在你特殊的dll中。Win32中常用的幾個dll是user32.dll, kernel32.dll和GDI32.dll.用dumpbin -exports kernel32.dll可以看到這個dll所有的API函數。

9,相互之間傳遞struct怎麼辦?我是說傳遞很複雜的struct?
傳遞一個結構,這個要用到StructLayoutAttribute屬性。比如:

PtInRect 具有以下非託管簽名:
BOOL PtInRect(const RECT *lprc, POINT pt);
請注意,由於函數需要指向 RECT 類型的指標,必須通過引用來傳遞 Rect 結構。

using System.Runtime.InteropServices;


[StructLayout(LayoutKind.Sequential)]

public struct Point 

{

     public int x;

     public int y;

}   

 

[StructLayout(LayoutKind.Explicit)]

public struct Rect 

{

     [FieldOffset(0)] public int left;

     [FieldOffset(4)] public int top;

     [FieldOffset(8)] public int right;

     [FieldOffset(12)] public int bottom;

}   

 

class Win32API 

{

     [DllImport("User32.dll")]

     public static extern bool PtInRect(ref Rect r, Point p);

}

10,哪裡有不錯的教程,我可以學到更詳細的東西?
google一下多的是。MSDN裡面也有一些不錯的教程:(vs.net 2003)

 

11,最後,這位大哥,你說了很多,我想問一個對我來說最關鍵的問題,我看了你的東西,似是而非,不會用怎麼辦?

這位兄弟勇氣可嘉,我給你準備了一個網站。這裡有一個PInvoke的Add-In tools for Visual Studio.Net,幾乎所有的Win32 API都有。安裝了以後,基本不用自己寫了。

平台叫用資料類型
提供管理的資料類型及其相應的非管理的資料類型的列表。
封送字串
描述如何通過值、通過引用、在結構中、在類中和在數組中傳遞字串。
封送類、結構和聯合
描述如何通過值傳遞類,如何傳遞各種結構以及如何傳遞具有值和混合類型的聯合。
封送類型數組
描述如何通過值傳遞多維整數數組以及如何通過引用傳遞一維數組。
其他封送處理樣本
描述影響 Interop 封送處理行為的記憶體回收和線程處理的各個方面。
http://www.pinvoke.net

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.