您的位置:首页 > 运维架构

.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

委托实例,可强制转换为适当的委托类型。

异常

异常条件
ArgumentExceptiont 参数不是委托或泛型。

ArgumentNullExceptionptr 参数为 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

一个可传递给非托管代码的值,非托管代码使用该值来调用基础托管委托。

异常

异常条件
ArgumentExceptiond 参数是泛型类型。

ArgumentNullExceptiond 参数为 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--------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: