.NET使用System.Runtime.InteropServices.Marshal实现委托与函数指针互转
2015-10-28 10:04
696 查看
函数介绍
摘自MSDN命名空间: System.Runtime.InteropServices
函数:Marshal.GetDelegateForFunctionPointer
(将非托管函数指针转换为委托)
publicstatic Delegate GetDelegateForFunctionPointer( IntPtr ptr, Type t )
参数
ptr类型:System.IntPtr
要转换的非托管函数指针。
t类型: System.Type
要返回的委托的类型。
返回值
类型: System.Delegate委托实例,可强制转换为适当的委托类型。
异常
异常 | 条件 |
---|---|
ArgumentException | t 参数不是委托或泛型。 |
ArgumentNullException | ptr 参数为 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing)。 - 或 - t 参数为 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing)。 |
在 .NET Framework 1.0 或 1.1 版中,可以将表示托管方法的委托作为函数指针传递给非托管代码,因此,非托管代码可以通过函数指针调用托管方法。非托管代码也可以将该函数指针传递回托管代码,指针可以正确解析为基础托管方法。
在 .NET Framework 2.0 及更高版本中,可以使用 GetDelegateForFunctionPointer 方法和GetFunctionPointerForDelegate 方法双向封送委托。 用
GetDelegateForFunctionPointer,ptr 将导入为System.IntPtr。
通过调用 GetFunctionPointerForDelegate 可以为托管委托获得
System.IntPtr,然后作为参数传递;此后可以从非托管方法中调用。
注意,在 .NET Framework 2.0 及更高版本中,参数封送拆收器还可将函数指针封送到委托。
GetDelegateForFunctionPointer 方法具有下列限制:
在互操作方案中不支持泛型。
不能将无效的函数指针传递给此方法。
此方法只能用于纯非托管函数指针。
不能将此方法用于通过 C++ 或从 GetFunctionPointer 方法获取的函数指针。
此方法不能用于由指向另一托管委托的函数指针创建委托。
.NET Framework 安全性
SecurityCriticalAttribute
需要完全信任直接调用方。此成员不能由部分受信任或透明的代码使用。
函数:Marshal.GetFunctionPointerForDelegate
(将委托转换为可从非托管代码调用的函数指针)
publicstatic IntPtr GetFunctionPointerForDelegate( Delegate d )
参数
d类型: System.Delegate要传递给非托管代码的委托。
返回值
类型: System.IntPtr一个可传递给非托管代码的值,非托管代码使用该值来调用基础托管委托。
异常
异常 | 条件 |
---|---|
ArgumentException | d 参数是泛型类型。 |
ArgumentNullException | d 参数为 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing)。 |
委托 d 转换为可使用 __stdcall 调用约定传递给非托管代码的函数指针。
必须以手动方式阻止垃圾回收器从托管代码中回收该委托。垃圾回收器不跟踪对非托管代码的引用。
例
例如一个函数指针定义为:typedef int (*FUN)(int iType,void *pvArgs);
而一个委托定义为:
public delegate int TEST_DLGT(int iType, IntPtr pvArgs);
则可以通过如下方法完成他们之间的互相转换
public delegate int TEST_DLGT(int iType, IntPtr pvArgs); public Form1() { TEST_DLGT funCallBack1 = new TEST_DLGT(this.testfun); IntPtr pvFun = Marshal.GetFunctionPointerForDelegate(funCallBack1);//可将pvFun强制转化为void*,再强制转化为FUN类型 TEST_DLGT funCallBack12 = (TEST_DLGT)Marshal.GetDelegateForFunctionPointer(pvFun, typeof(TEST_DLGT)); }
在托管C++中,则应写为:
int ClassName::Start(TEST_DLGT ^funCallBack1)//委托通常在托管代码(C#)中创建,传入由托管C++封装的类库。这里假设ClassName是一个CLR类库的接口类。 { FUN pfun1=(FUN)(void*)Marshal::GetFunctionPointerForDelegate(funCallBack1); TEST_DLGT ^funCallBack2=(TEST_DLGT^)Marshal::GetDelegateForFunctionPointer((IntPtr)(void*)pfun1, TEST_DLGT::typeid); return 0; }
----------------------------EOB--------------------------------
相关文章推荐
- Shell脚本:使用rsync备份文件/目录
- 通过select的text来选中对应的option
- 查看linux下的字体
- Shell脚本:使用rsync备份文件/目录
- UVa 10849 - Move the bishop
- Shell脚本:使用rsync备份文件/目录
- apache与IIS公用80端口(转发代理)
- Apache快速配置
- Spring + Dubbo + zookeeper (linux) 框架搭建
- 每天一个Linux命令-25(pgrep)
- Linux系统下chkconfig命令使用详解
- linux while循环
- 台达PLC与紫金桥监控组态软件的连接
- linux top命令详解
- 每天一个linux命令(24):Linux文件类型与扩展名
- Linux环境下段错误的产生原因及调试方法小结
- Shell脚本处理“integer expression expected”
- tomcat加载类的顺序
- Checking System Drive Free Space with WMI and PowerShell
- Centos7下支付宝控件安装