我正在使用 Mono.Ceil 打包 C# 代码,以便在函数中插入代码存根。这是我的代码
对于枚举类型,即 ValueType,我使用 OpCodes.box 将其装箱为对象。如果不使用 il2cpp(形式 Unity3D)翻译成 C++ 代码,它就可以工作。
它生成不正确(var L_3 未装箱),
// System.Void ToBePatched::FuncWithEnum(ToBePatched/MyEnum)
extern Il2CppClass* ObjectU5BU5D_t3632007997_il2cpp_TypeInfo_var;
extern Il2CppClass* Exception_t1145979430_il2cpp_TypeInfo_var;
extern const MethodInfo* ToBePatched_FuncWithEnum_m3969224534_MethodInfo_var;
extern Il2CppCodeGenString* _stringLiteral880614685;
extern Il2CppCodeGenString* _stringLiteral2366206808;
extern const uint32_t ToBePatched_FuncWithEnum_m3969224534_MetadataUsageId;
extern "C" void ToBePatched_FuncWithEnum_m3969224534 (ToBePatched_t3077132781 * __this, int32_t ___a0, const MethodInfo* method)
{
static bool s_Il2CppMethodIntialized;
if (!s_Il2CppMethodIntialized)
{
il2cpp_codegen_initialize_method (ToBePatched_FuncWithEnum_m3969224534_MetadataUsageId);
s_Il2CppMethodIntialized = true;
}
ObjectU5BU5D_t3632007997* V_0 = NULL;
Il2CppObject * V_1 = NULL;
{
MethodBase_t591550820 * L_0 = MethodBase_GetMethodFromHandle_m3983882276(NULL /*static, unused*/, LoadMethodToken(ToBePatched_FuncWithEnum_m3969224534_MethodInfo_var), /*hidden argument*/NULL);
ObjectU5BU5D_t3632007997* L_1 = ((ObjectU5BU5D_t3632007997*)SZArrayNew(ObjectU5BU5D_t3632007997_il2cpp_TypeInfo_var, (uint32_t)((int32_t)1)));
V_0 = L_1;
ObjectU5BU5D_t3632007997* L_2 = L_1;
int32_t L_3 = ___a0; // L_3 not boxed
NullCheck(L_2);
IL2CPP_ARRAY_BOUNDS_CHECK(L_2, ((int32_t)0));
ArrayElementTypeCheck (L_2, L_3); // error here
(L_2)->SetAt(static_cast<il2cpp_array_size_t>(((int32_t)0)), (Il2CppObject *)L_3);
bool L_4 = LuaHotPatchLoader_Hub_m392557439(NULL /*static, unused*/, _stringLiteral880614685, L_0, __this, (&V_1), L_2, /*hidden argument*/NULL);
if (!L_4)
{
goto IL_0038;
}
}
{
return;
}
IL_0038:
{
Exception_t1145979430 * L_5 = (Exception_t1145979430 *)il2cpp_codegen_object_new(Exception_t1145979430_il2cpp_TypeInfo_var);
Exception__ctor_m485833136(L_5, _stringLiteral2366206808, /*hidden argument*/NULL);
IL2CPP_RAISE_MANAGED_EXCEPTION(L_5);
}
}
但是对于未修补枚举的 func,它生成正确,(var L_3 boxed)
// System.Void ToBePatched::TestEnum(ToBePatched/MyEnum)
extern Il2CppClass* ObjectU5BU5D_t3632007997_il2cpp_TypeInfo_var;
extern Il2CppClass* Int32_t1448170597_il2cpp_TypeInfo_var;
extern const uint32_t ToBePatched_TestEnum_m1559027260_MetadataUsageId;
extern "C" void ToBePatched_TestEnum_m1559027260 (ToBePatched_t3077132781 * __this, int32_t ___m0, const MethodInfo* method)
{
static bool s_Il2CppMethodIntialized;
if (!s_Il2CppMethodIntialized)
{
il2cpp_codegen_initialize_method (ToBePatched_TestEnum_m1559027260_MetadataUsageId);
s_Il2CppMethodIntialized = true;
}
Il2CppObject * V_0 = NULL;
{
ObjectU5BU5D_t3632007997* L_0 = ((ObjectU5BU5D_t3632007997*)SZArrayNew(ObjectU5BU5D_t3632007997_il2cpp_TypeInfo_var, (uint32_t)1));
int32_t L_1 = ___m0;
int32_t L_2 = ((int32_t)L_1);
Il2CppObject * L_3 = Box(Int32_t1448170597_il2cpp_TypeInfo_var, &L_2);
NullCheck(L_0);
IL2CPP_ARRAY_BOUNDS_CHECK(L_0, 0);
ArrayElementTypeCheck (L_0, L_3);
(L_0)->SetAt(static_cast<il2cpp_array_size_t>(0), (Il2CppObject *)L_3);
ToBePatched_TestEnum2_m129206415(__this, (&V_0), L_0, /*hidden argument*/NULL);
return;
}
}
它们具有相同的(至少对我而言)IL 代码(IL_0013 ~ IL_001d),
.method public hidebysig
instance void FuncWithEnum (
valuetype ToBePatched/MyEnum a
) cil managed
{
// Method begins at RVA 0x7ac0
// Code size 59 (0x3b)
.maxstack 8
.locals (
[0] object[],
[1] object
)
IL_0000: ldstr "System.Void ToBePatched::FuncWithEnum(ToBePatched/MyEnum)"
IL_0005: ldtoken method instance void ToBePatched::FuncWithEnum(valuetype ToBePatched/MyEnum)
IL_000a: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
IL_000f: ldarg.0
IL_0010: ldloca.s 1
IL_0012: ldc.i4.1
IL_0013: newarr [mscorlib]System.Object
IL_0018: dup
IL_0019: stloc.0
IL_001a: dup
IL_001b: ldc.i4.0
IL_001c: ldarg.1
IL_001d: box ToBePatched/MyEnum
IL_0022: stelem.ref
IL_0023: call bool ['Assembly-CSharp-firstpass']lua.hotpatch.LuaHotPatchLoader::Hub(string, class [mscorlib]System.Reflection.MethodBase, object, object&, object[])
IL_0028: brfalse IL_002f
IL_002d: nop
IL_002e: ret
IL_002f: nop
IL_0030: ldstr "not patched"
IL_0035: newobj instance void [mscorlib]System.Exception::.ctor(string)
IL_003a: throw
} // end of method ToBePatched::FuncWithEnum
和 (IL_0004 ~ IL_000c)
.method public hidebysig
instance void TestEnum (
valuetype ToBePatched/MyEnum m
) cil managed
{
// Method begins at RVA 0x7bf4
// Code size 24 (0x18)
.maxstack 7
.locals init (
[0] object
)
IL_0000: ldarg.0
IL_0001: ldloca.s 0
IL_0003: ldc.i4.1
IL_0004: newarr [mscorlib]System.Object
IL_0009: dup
IL_000a: ldc.i4.0
IL_000b: ldarg.1
IL_000c: box [mscorlib]System.Int32
IL_0011: stelem.ref
IL_0012: call instance void ToBePatched::TestEnum2(object&, object[])
IL_0017: ret
} // end of method ToBePatched::TestEnum
我想念什么?
附加信息,我发现对于其他非原始值类型(结构值),它有同样的问题,L_4 装箱为 L_5,但 L_7 没有装箱。
Il2CppObject * V_8 = NULL;
{
MethodBase_t3461000640 * L_0 = MethodBase_GetMethodFromHandle_m3548347628(NULL /*static, unused*/, LoadMethodToken(ObjectFactory_CreateBattlePawn_m252190338_MethodInfo_var), /*hidden argument*/NULL);
ObjectU5BU5D_t11523773* L_1 = ((ObjectU5BU5D_t11523773*)SZArrayNew(ObjectU5BU5D_t11523773_il2cpp_TypeInfo_var, (uint32_t)((int32_t)3)));
V_7 = L_1;
ObjectU5BU5D_t11523773* L_2 = L_1;
int32_t L_3 = ___soldierId0; // primitive value type
int32_t L_4 = L_3;
Il2CppObject * L_5 = Box(Int32_t2847414787_il2cpp_TypeInfo_var, &L_4); // boxed
NullCheck(L_2);
IL2CPP_ARRAY_BOUNDS_CHECK(L_2, ((int32_t)0));
ArrayElementTypeCheck (L_2, L_5);
(L_2)->SetAt(static_cast<il2cpp_array_size_t>(((int32_t)0)), (Il2CppObject *)L_5);
ObjectU5BU5D_t11523773* L_6 = L_2;
Vector3_t3525329789 L_7 = ___position1; // non-primitive value type, a struct value
NullCheck(L_6);
IL2CPP_ARRAY_BOUNDS_CHECK(L_6, ((int32_t)1));
ArrayElementTypeCheck (L_6, L_7); // error here
(L_6)->SetAt(static_cast<il2cpp_array_size_t>(((int32_t)1)), (Il2CppObject *)L_7);