論壇首頁
-> IT人生
ZT: .NET Interop入門-P/Invoke和Reverse P/Invoke (發表於15年前)
|
|
|
|
閱讀上一個主題 :: 閱讀下一個主題 |
作者 |
正文 |
webdriver (只看此人)
|
時間: 2009-4-05 23:10
|
|
|
最近在論壇上經常看到一些基本的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,就和調用其他托管代碼一樣輕松自如了。
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把這個委托傳給了本地代碼。本地代碼可以如下調用托管代碼:
代碼: |
#include <stdio.h>
#include <wtypes.h>
extern "C" {
__declspec(dllexport) void NativeMethod(void (__stdcall *pShowMsgBox)(WCHAR *wChar))
{
(*pShowMsgBox)(L"hello reverse interop");
}
}
|
注意到托管代碼中的委托到了本地代碼中,就是一個函數指針,本地代碼可以像一個普通的函數指針一般調用托管代碼。
大家可能注意到dll的聲明用了extern “C”,它指明了調用規范是cdecl,在之前的托過代碼的DllImport中,也相應的注明了調用約定,關於調用約定的詳細介紹,可以參見我的另一篇博客。
今天的介紹就到這裡,大家可以把這些示例代碼當作一個template,根據實際需求作相應的具體改動。
Published Sunday, March 29, 2009 12:24 AM by SilverlightShanghai
Filed under: CLR Interop, .NET小貼士
_________________ There is no wisdom tree; nor a stand of a mirror bright, Since all is void, where can the dust alight?
|
|
|
上一次由webdriver於2009-4-05 23:52修改,總共修改了1次
|
|
樓主 |
電梯直達
|
|
Castro (只看此人)
|
時間: 2009-4-05 23:19
|
|
|
|
|
|
沙發 |
返回頂端
|
|
nessus (只看此人)
|
時間: 2009-6-07 09:54
|
|
|
不錯。直接到他們的團隊blog上看了看,東西不多不過他們自己開發的一個tool - TlmImp2挺不錯的。可以直接調用COM庫,然後生成Interop Assembly。
|
|
|
板凳 |
返回頂端
|
|
飛舞的音符 (只看此人)
|
時間: 2009-6-16 23:03
|
|
|
學習中。。。
|
|
|
地板 |
返回頂端
|
|
|
|
論壇首頁
-> IT人生 |
所有的時間均為 美國太平洋時間
|
第1頁,共1頁 |
|
|
注: 以上論壇所有發言僅代表發帖者個人觀點, 並不代表本站觀點或立場, 加西網對此不負任何責任。 投資理財及買房賣房版面的帖子不構成投資建議。投資有風險,責任請自負對二手買賣中的虛假信息,買賣中的糾紛等均與本站無關。 |
|
您不能在本論壇發表新主題 您不能在本論壇回復主題 您不能在本論壇編輯自己的文章 您不能在本論壇刪除自己的文章 您不能在本論壇發表投票 您不能在這個論壇添加附件 您可以在這個論壇下載文件
論壇轉跳:
|
|
webdriver, Castro, nessus, 飛舞的音符
|
|
|