MSIL存储要返回的结构值

本文关键字:结构 返回 存储 MSIL | 更新日期: 2023-09-27 17:59:02

我正在使用RemotingLite库(请参阅github),代理类工厂有问题。简而言之,问题在于生成返回ValueType对象(如用户定义的结构)的代码时。

这里是原始代码的一部分:

...
mIL.Emit(OpCodes.Ldloc, resultLB.LocalIndex); //load the result array
mIL.Emit(OpCodes.Ldc_I4, 0); //load the index of the return value. Alway 0
mIL.Emit(OpCodes.Ldelem_Ref); //load the value in the index of the array
if (returnType.IsValueType)
{
    mIL.Emit(OpCodes.Unbox, returnType); //unbox it
    mIL.Emit(ldindOpCodeTypeMap[returnType]);
}
else
    mIL.Emit(OpCodes.Castclass, returnType);
}
        mIL.Emit(OpCodes.Ret);

ldindOpCodeTypeMap是一个具有OpCodes.Ldind_U2等操作码的字典。因此它只适用于Int16, Int32等标准MSIL类型。但是,如果我需要推送到堆栈,然后返回自定义的ValueType值(例如-Guid-大小为16字节),我需要做什么?

例如:

...
mIL.Emit(OpCodes.Unbox, returnType); //unbox it
OpCode opcode;
if (ldindOpCodeTypeMap.TryGetValue(returnType, out opcode))
{
    mIL.Emit(ldindOpCodeTypeMap[returnType]);
}
else
{
    // here I getting the size of custom type
    var size = System.Runtime.InteropServices.Marshal.SizeOf(returnType);
    // what next?
}
...

这里我得到了一个自定义ValueType值的大小。那么,如何像Ldind_x操作码那样将自定义ValueType的值间接加载到评估堆栈上呢?谢谢

MSIL存储要返回的结构值

Ldobj将执行您想要的操作。但是,您也可以用Unbox_Any替换整个条件:它将完成值类型或引用类型所需的一切。

您发布代码的完整替代品将是:

...
mIL.Emit(OpCodes.Ldloc, resultLB.LocalIndex); //load the result array
mIL.Emit(OpCodes.Ldc_I4, 0); //load the index of the return value. Alway 0
mIL.Emit(OpCodes.Ldelem_Ref); //load the value in the index of the array
mIL.Emit(OpCodes.Unbox_Any, returnType);
mIL.Emit(OpCodes.Ret);