非静态回调如何在本机代码中工作
本文关键字:本机代码 工作 静态 回调 | 更新日期: 2023-09-27 18:06:14
问这个问题有点奇怪,因为我的代码看起来不应该工作,但它确实工作,虽然我不是在抱怨,但我想确认为什么?LOL
简单地说,我有一个c++本地DLL(根本没有CLR/托管支持),它从c#代码中接受回调。本机端存储一个stdcall回调函数,该函数由c#端提供。我一直认为回调方法(在c#中)必须是静态的,但非静态和lambda表达式都工作得很好!如何从本机代码封送"this"指针?我一直认为本机代码只存储非实例函数指针?
现在,我确实找到了一篇文章,其中有人发布了IL代码来"桥接"本机和非静态托管回调。我还注意到这个折旧方法:"Marshal.GetUnmanagedThunkForManagedMethodPtr()"。该方法不再支持,我假设这意味着它是内置的?
问题总结:
-
思考现在是内置到。net通过发射IL代码?如果是这样,那么在。net的哪个版本中它成为本机支持的?
-
在Mono中是否也支持隐式"思考"?
-
当为托管回调发出IL时,会发生什么think所指的实例被删除了吗?IL被移除了吗这可能会导致内存"泄漏"吗?
谢谢。
思考现在是通过发出IL代码内置到。net中的吗?如果是这样,那么在。net的哪个版本中它成为本机支持的?
不涉及IL,它通过发出本机代码来实现——一个重新排列参数以满足。net调用约定的蹦床,包括在关闭委托的情况下保存的this
指针,然后对。net方法本身执行尾部调用。
在Mono中也支持隐式"思考"吗?
这被称为"反向p/invoke",这应该使它很容易在Mono文档中查找。
当为托管回调发出IL时,当它所引用的实例被删除时会发生什么?
当委托被垃圾收集时,蹦床使用的内存也被释放。所以只要本机代码有一个指向蹦床的指针,你就需要保持委托存活。
互操作编组程序只是编组一个委托。委托可以是类委托(没有this
)或实例委托(有this
)。从c#的角度来看,它只是调用委托。例如,使用实例委托管理this
的相同语义(例如,类实例的解耦)被有效地使用。
显然还有其他事情在幕后发生(比如钉,等等)——但它们通常与你所问的无关。