.NET Interop入門-P/Invoke和Reverse P/Invoke

來源:互聯網
上載者:User

最近在論壇上經常看到一些基本的interop的問題,給我動力寫完之前的.net interop入門系列,給剛剛涉足.NET  interop的朋友們一個大體上的概念。

每每談及.NET interop,我的腦中總是出現下面一幅圖:

該圖代表了.net interop的四個典型情境。之前我的同事和我討論了.NET和COM互操作的應用:

  • 在.NET中調用COM:COM Interop入門
  • 在COM中調用.NET:在COM應用中使用.NET組件,使用IDispatch::Invoke函數在C++中調用C#實現的託管類庫方法。

今天我主要講一下P/Invoke和Reverse P/Invoke,和COM interop相比,P/Invoke無需註冊組件,使用上更輕量,更綠色。

1. P/Invoke

P/Invoke(platform invoke)是.NET調用本地代碼(native code)的一種比較輕便的方式。只需要將本地代碼編寫成動態連結程式庫,然後在c#代碼中,聲明一個外部靜態函數,並且用DllImport屬性指明動態串連庫的入口。舉例如下:

using System;using System.Runtime.InteropServices;class PInvoke{    [DllImportAttribute("user32.dll", EntryPoint = "MessageBoxW")]    public static extern  int MessageBoxW(        [In]System.IntPtr hWnd,        [In][MarshalAs(UnmanagedType.LPWStr)] string lpText,        [In][MarshalAs(UnmanagedType.LPWStr)] string lpCaption,        uint uType);    public static void Main()    {        MessageBoxW(IntPtr.Zero, "Hello", "Interop", 0);    }}

稍加解釋這個代碼。類PInvoke中,有個MessageBoxW的函式宣告,它的實現在user32.dll(系統內建)中,入口是MessageBoxW,參數的構成是根據windows API的聲明而定的,我們在Codeplex上有一個工具,專門協助大家聲稱一個本地代碼(c++)編寫的函數在託過代碼(c#)中的函式宣告,之前我們團隊的成員也撰文介紹了這個工具的使用。

有了這個聲明以後,在Main中調用MessageBox,就和調用其他Managed 程式碼一樣輕鬆自如了。

2. Reverse P/Invoke

接著,我們來看看在本地代碼中調用.NET方法。本地代碼需要拿到一個.NET委託(delegate),然後把這個delegate當作一個函數指標使用,樣本如下:

using System;using System.Windows.Forms;using System.Runtime.InteropServices;public class Program{    internal delegate void DelegateMessageBox([MarshalAs(UnmanagedType.LPWStr)]string msg);    [DllImport("Native.dll", CallingConvention = CallingConvention.Cdecl)]    static extern void NativeMethod(DelegateMessageBox d);    public static void ShowMessageBox(string msg)    {       MessageBox.Show(msg);    }    public static void Main()    {        NativeMethod(new DelegateMessageBox(ShowMessageBox));    }}

這個例子中,我們希望本地代碼能夠調用託管函數ShowMessageBox來顯示一個對話方塊。為了讓本地代碼可以調用這個函數,我們根據它的聲明,定了了一個delegate,並且通過P/Invoke把這個委託傳給了本地代碼。本地代碼可以如下調用Managed 程式碼:

#include <stdio.h>#include <wtypes.h>extern "C" {    __declspec(dllexport) void NativeMethod(void (__stdcall *pShowMsgBox)(WCHAR *wChar))    {        (*pShowMsgBox)(L"hello reverse interop");    }}

注意到Managed 程式碼中的委託到了本地代碼中,就是一個函數指標,本地代碼可以像一個普通的函數指標一般調用Managed 程式碼。

大家可能注意到dll的聲明用了extern “C”,它指明了調用規範是cdecl,在之前的託過代碼的DllImport中,也相應的註明了呼叫慣例,關於呼叫慣例的詳細介紹,可以參見我的另一篇部落格。

今天的介紹就到這裡,大家可以把這些範例程式碼當作一個template,根據實際需求作相應的具體改動。

http://blogs.msdn.com/b/silverlightshanghai/archive/2009/03/29/net-interop-p-invoke-reverse-p-invoke.aspx

聯繫我們

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