ZT: .NET Interop入門-P/Invoke和Reverse P/Invoke
文章內容
最近在論壇上經常看到一些基本的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屬性指明動態連接庫的入口。舉例如下:
稍加解釋這個代碼。類PInvoke中,有個MessageBoxW的函數聲明,它的實現在user32.dll(系統自帶)中,入口是MessageBoxW,參數的構成是根據windows API的聲明而定的,我們在Codeplex上有一個工具,專門幫助大家聲稱一個本地代碼(c++)編寫的函數在托過代碼(c#)中的函數聲明,之前我們團隊的成員也撰文介紹了這個工具的使用。
有了這個聲明以後,在Main中調用MessageBox,就和調用其他托管代碼一樣輕松自如了。
2. Reverse P/Invoke
接著,我們來看看在本地代碼中調用.NET方法。本地代碼需要拿到一個.NET委托(delegate),然後把這個delegate當作一個函數指針使用,示例如下:
這個例子中,我們希望本地代碼能夠調用托管函數ShowMessageBox來顯示一個對話框。為了讓本地代碼可以調用這個函數,我們根據它的聲明,定了了一個delegate,並且通過P/Invoke把這個委托傳給了本地代碼。本地代碼可以如下調用托管代碼:
注意到托管代碼中的委托到了本地代碼中,就是一個函數指針,本地代碼可以像一個普通的函數指針一般調用托管代碼。
大家可能注意到dll的聲明用了extern “C”,它指明了調用規范是cdecl,在之前的托過代碼的DllImport中,也相應的注明了調用約定,關於調用約定的詳細介紹,可以參見我的另一篇博客。
今天的介紹就到這裡,大家可以把這些示例代碼當作一個template,根據實際需求作相應的具體改動。
Published Sunday, March 29, 2009 12:24 AM by SilverlightShanghai
Filed under: CLR Interop, .NET小貼士
每每談及.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; |
稍加解釋這個代碼。類PInvoke中,有個MessageBoxW的函數聲明,它的實現在user32.dll(系統自帶)中,入口是MessageBoxW,參數的構成是根據windows API的聲明而定的,我們在Codeplex上有一個工具,專門幫助大家聲稱一個本地代碼(c++)編寫的函數在托過代碼(c#)中的函數聲明,之前我們團隊的成員也撰文介紹了這個工具的使用。
有了這個聲明以後,在Main中調用MessageBox,就和調用其他托管代碼一樣輕松自如了。
2. Reverse P/Invoke
接著,我們來看看在本地代碼中調用.NET方法。本地代碼需要拿到一個.NET委托(delegate),然後把這個delegate當作一個函數指針使用,示例如下:
代碼: |
using System; |
這個例子中,我們希望本地代碼能夠調用托管函數ShowMessageBox來顯示一個對話框。為了讓本地代碼可以調用這個函數,我們根據它的聲明,定了了一個delegate,並且通過P/Invoke把這個委托傳給了本地代碼。本地代碼可以如下調用托管代碼:
代碼: |
#include <stdio.h> |
注意到托管代碼中的委托到了本地代碼中,就是一個函數指針,本地代碼可以像一個普通的函數指針一般調用托管代碼。
大家可能注意到dll的聲明用了extern “C”,它指明了調用規范是cdecl,在之前的托過代碼的DllImport中,也相應的注明了調用約定,關於調用約定的詳細介紹,可以參見我的另一篇博客。
今天的介紹就到這裡,大家可以把這些示例代碼當作一個template,根據實際需求作相應的具體改動。
Published Sunday, March 29, 2009 12:24 AM by SilverlightShanghai
Filed under: CLR Interop, .NET小貼士
分享: | 分享到微信 |
文章評論
Castro | 無題 DING!
2009-04-05 23:19:17 | 引用 |
無題 不錯。直接到他們的團隊blog上看了看,東西不多不過他們自己開發的一個tool - TlmImp2挺不錯的。可以直接調用COM庫,然後生成Interop Assembly。
2009-06-07 09:54:10 | 引用 |
nessus |
飛舞的音符 | Re: ZT: .NET Interop入門-P/Invoke和Reverse P/Invoke 學習中。。。
2009-06-16 23:03:49 | 引用 |