c# - 在 Calli 指令中使用 Reflection.Emit 生成 modopt
问题描述
我正在尝试使用 Reflection.Emit 为Call
以下代码的方法生成代码:
public unsafe class Program
{
public struct ATest
{
public int Test;
}
public struct Test
{
public Vtable* vtbl;
public struct Vtable
{
public delegate * unmanaged[Stdcall]<Test*, ATest> ptr;
}
}
public static ATest Call(Test* instance)
{
return ((delegate * unmanaged[Stdcall, MemberFunction]<Test*, ATest>)instance->vtbl->ptr)(instance);
}
}
我已经使用sharplab.io反编译了该方法并得到了以下msil:
// Methods
.method public hidebysig static
valuetype Program/ATest Call (
valuetype Program/Test* 'instance'
) cil managed
{
// Method begins at RVA 0x2050
// Code size 25 (0x19)
.maxstack 2
.locals init (
[0] method unmanaged valuetype Program/ATest modopt([System.Private.CoreLib]System.Runtime.CompilerServices.CallConvMemberFunction) modopt([System.Private.CoreLib]System.Runtime.CompilerServices.CallConvStdcall) *(valuetype Program/Test*),
[1] valuetype Program/ATest
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld valuetype Program/Test/Vtable* Program/Test::vtbl
IL_0007: ldfld method unmanaged stdcall valuetype Program/ATest *(valuetype Program/Test*) Program/Test/Vtable::ptr
IL_000c: stloc.0
IL_000d: ldarg.0
IL_000e: ldloc.0
IL_000f: calli unmanaged valuetype Program/ATest modopt([System.Private.CoreLib]System.Runtime.CompilerServices.CallConvMemberFunction) modopt([System.Private.CoreLib]System.Runtime.CompilerServices.CallConvStdcall)(valuetype Program/Test*)
IL_0014: stloc.1
IL_0015: br.s IL_0017
IL_0017: ldloc.1
IL_0018: ret
} // end of method Program::Call
我尝试使用反射.emit 生成 MSIL 指令,但我不知道如何发出该行IL_000f
:
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, vtableField);
il.Emit(OpCodes.Ldfld, methodField);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldloc_0);
il.EmitCalli(???);
问题是,MSIL 中的这条线同时具有modopt(MemberFunction)
and mopopt(Stdcall)
,我没有看到这在il.EmitCalli
方法中的任何地方都暴露出来。
有人可以帮忙吗?
解决方案
如问题https://github.com/dotnet/runtime/issues/11354中所述,目前无法在反射堆栈中使用函数指针(当前typeof(delegate* ...)
始终返回IntPtr
),因此无法使 Reflection.Emit 可靠地工作在这种情况下。
推荐阅读
- flutter - 在最近的应用程序视图中如何处理窗口可见性
- mysql - 如何在云构建中安装 mysql 并运行脚本?
- postgresql - PostgreSQL 查询不使用索引
- javascript - 在 Map 和 navigator.geolocation 上使用 Leaflet 的多个事件
- python - 让 Livereload + Flask 触发硬刷新
- python - 如何创建强化学习神经网络来玩飞扬的小鸟?
- javascript - 为什么在 Chrome 扩展程序中请求时出现 CORB 问题?
- jquery - 无法在 select2 中读取 null 的属性“concat”
- java - 按下微调器下拉菜单时,禁用全屏模式
- node.js - Athena Node.js AWS 开发工具包 - 任何请求都会引发 InvalidRequestException