5

问这个问题有点奇怪,因为我的代码似乎不应该工作,但它确实有效,虽然我没有抱怨,但我想确认为什么?哈哈

简单地说,我有一个 C++ 本机 DLL(根本没有 CLR/托管支持),它从 C# 代码中获取回调。native 端存储一个 stdcall 回调函数,由 C# 端提供。我一直认为回调方法(在 C# 中)必须是静态的,但非静态和 lambda 表达式都可以正常工作!?如何从本机代码封送“this”指针?我一直以为原生代码只存储非实例函数指针?

现在,我确实找到了一篇文章,其中有人发出 IL 代码以在本机和非静态托管回调之间“架起”桥梁。我还注意到了这种贬值的方法:“Marshal.GetUnmanagedThunkForManagedMethodPtr()”。该方法不再受支持,我假设这意味着它是内置的?

问题总结:

  1. thunking 现在是通过发出 IL 代码在 .NET 中内置的吗?如果是这样,它在哪个版本的 .NET 中成为本机支持的?

  2. Mono 是否也支持隐式“thunking”?

  3. 当为托管回调发出 IL 时,当 thunk 引用的实例被删除时会发生什么?IL 是否被删除,或者这可能会导致内存“泄漏”?

谢谢。

4

2 回答 2

2

thunking 现在是通过发出 IL 代码在 .NET 中内置的吗?如果是这样,它在哪个版本的 .NET 中成为本机支持的?

thunk 中不涉及 IL,它是通过发出本机代码来发生的——一个重新排列参数以满足 .NET 调用约定的蹦床,包括在this关闭委托的情况下保存的指针,然后对 .NET 执行尾调用方法本身。

Mono 是否也支持隐式“thunking”?

这称为“反向 p/invoke”,应该可以在 Mono 文档中轻松查找。

当为托管回调发出 IL 时,当 thunk 引用的实例被删除时会发生什么?

当委托被垃圾回收时,蹦床使用的内存也被释放。因此,只要本机代码具有指向蹦床的指针,您就需要让委托保持活动状态。

于 2013-03-27T18:17:21.917 回答
1

互操作编组器只是编组一个代表。委托可以是类委托(没有this)或实例委托(有this)。从 C# 的角度来看,它只是调用一个委托。即this有效地使用了用于管理实例委托的相同语义(例如,类实例的解耦)。

很明显,还有其他事情(如钉住等)在幕后发生了更多事情——但它们通常与你所问的无关。

于 2013-03-27T18:15:34.900 回答