论坛首页
-> 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, 飞舞的音符
|
|
|