1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-11 04:52:21 +02:00

Reflection SetField fixes

This commit is contained in:
Brian Fiete 2020-08-25 07:08:44 -07:00
parent d864a912c5
commit eda4e80715
2 changed files with 89 additions and 21 deletions

View file

@ -46,25 +46,27 @@ namespace System.Reflection
public Result<void, Error> SetValue(Object obj, Object value) public Result<void, Error> SetValue(Object obj, Object value)
{ {
int32 dataOffsetAdjust = 0; void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj));
if (mTypeInstance.IsStruct) if (mTypeInstance.IsStruct)
{ {
Type boxedType = obj.[Friend]RawGetType(); Type boxedType = obj.[Friend]RawGetType();
bool typeMatched = false; bool typeMatched = false;
if (boxedType.IsBoxed) if (boxedType.IsBoxed)
{ {
if (mTypeInstance == boxedType.UnderlyingType) if (mTypeInstance == boxedType.UnderlyingType)
{ {
dataOffsetAdjust = boxedType.[Friend]mMemberDataOffset; dataAddr = (void*)((int)dataAddr + boxedType.[Friend]mMemberDataOffset);
typeMatched = true; if (boxedType.IsBoxedStructPtr)
} dataAddr = *(void**)dataAddr;
} typeMatched = true;
}
}
if (!typeMatched) if (!typeMatched)
return .Err(.InvalidTargetType); // "Invalid target type"); return .Err(.InvalidTargetType); // "Invalid target type");
} }
dataAddr = (void*)((int)dataAddr + mFieldData.mData);
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
void* fieldDataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)) + (int)mFieldData.mData + dataOffsetAdjust;
if (value == null) if (value == null)
{ {
@ -74,13 +76,15 @@ namespace System.Reflection
} }
else else
{ {
*((int*)fieldDataAddr) = 0; *((int*)dataAddr) = 0;
return .Ok; return .Ok;
} }
} }
Type rawValueType = value.[Friend]RawGetType(); Type rawValueType = value.[Friend]RawGetType();
void* valueDataAddr = ((uint8*)Internal.UnsafeCastToPtr(value)) + rawValueType.[Friend]mMemberDataOffset; void* valueDataAddr = ((uint8*)Internal.UnsafeCastToPtr(value)) + rawValueType.[Friend]mMemberDataOffset;
if (rawValueType.IsBoxedStructPtr)
valueDataAddr = *(void**)valueDataAddr;
Type valueType = value.GetType(); Type valueType = value.GetType();
@ -90,9 +94,9 @@ namespace System.Reflection
if (valueType == fieldType) if (valueType == fieldType)
{ {
if (valueType.IsObject) if (valueType.IsObject)
*((void**)fieldDataAddr) = Internal.UnsafeCastToPtr(value); *((void**)dataAddr) = Internal.UnsafeCastToPtr(value);
else else
Internal.MemCpy(fieldDataAddr, valueDataAddr, fieldType.[Friend]mSize); Internal.MemCpy(dataAddr, valueDataAddr, fieldType.[Friend]mSize);
} }
else else
{ {
@ -104,7 +108,7 @@ namespace System.Reflection
public Result<void> SetValue(Object obj, Variant value) public Result<void> SetValue(Object obj, Variant value)
{ {
int32 dataOffsetAdjust = 0; void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj));
if (mTypeInstance.IsStruct) if (mTypeInstance.IsStruct)
{ {
Type boxedType = obj.[Friend]RawGetType(); Type boxedType = obj.[Friend]RawGetType();
@ -113,20 +117,31 @@ namespace System.Reflection
{ {
if (mTypeInstance == boxedType.UnderlyingType) if (mTypeInstance == boxedType.UnderlyingType)
{ {
dataOffsetAdjust = boxedType.[Friend]mMemberDataOffset; dataAddr = (void*)((int)dataAddr + boxedType.[Friend]mMemberDataOffset);
if (boxedType.IsBoxedStructPtr)
dataAddr = *(void**)dataAddr;
typeMatched = true; typeMatched = true;
} }
} }
if (!typeMatched) if (!typeMatched)
return .Err;//("Invalid target type"); return .Err;//("Invalid target type");
} }
dataAddr = (void*)((int)dataAddr + mFieldData.mData);
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)) + (int)mFieldData.mData + dataOffsetAdjust;
if (value.VariantType != fieldType) let variantType = value.VariantType;
return .Err;//("Invalid type"); if (variantType != fieldType)
{
if ((variantType.IsPointer) && (variantType.UnderlyingType == fieldType))
{
void* srcPtr = value.Get<void*>();
Internal.MemCpy(dataAddr, srcPtr, fieldType.Size);
return .Ok;
}
else
return .Err;//("Invalid type");
}
value.CopyValueData(dataAddr); value.CopyValueData(dataAddr);
@ -149,6 +164,8 @@ namespace System.Reflection
/*if (type.IsStruct) /*if (type.IsStruct)
return &value;*/ return &value;*/
if (type.IsBoxedStructPtr)
return *(void**)(((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset);
if (type.IsBoxed) if (type.IsBoxed)
return ((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset; return ((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset;
return ((uint8*)Internal.UnsafeCastToPtr(value)); return ((uint8*)Internal.UnsafeCastToPtr(value));

View file

@ -125,11 +125,18 @@ namespace Tests
} }
} }
struct StructC
{
public float mA;
public float mB;
}
[Reflect, AlwaysInclude(AssumeInstantiated=true, IncludeAllMethods=true)] [Reflect, AlwaysInclude(AssumeInstantiated=true, IncludeAllMethods=true)]
struct StructB struct StructB
{ {
public int mA; public int mA;
public String mB; public String mB;
public StructC mC;
} }
class ClassA2 : ClassA class ClassA2 : ClassA
@ -485,20 +492,64 @@ namespace Tests
StructB sb; StructB sb;
sb.mA = 25; sb.mA = 25;
sb.mB = "Struct B"; sb.mB = "Struct B";
sb.mC = .() { mA = 1.2f, mB = 2.3f };
let type = sb.GetType() as TypeInstance; let type = sb.GetType() as TypeInstance;
let fields = type.GetFields(); let fields = type.GetFields();
int fieldIdx = 0; int fieldIdx = 0;
for (let field in fields) for (let field in fields)
{ {
let refP = field.GetValue(sb); let fieldVal = field.GetValue(sb);
let fieldVal2 = field.GetValue(&sb);
switch (fieldIdx) switch (fieldIdx)
{ {
case 0: case 0:
Test.Assert(refP.Value.Get<int>() == 25); Test.Assert(fieldVal.Value.Get<int>() == 25);
Variant newVal = Variant.Create<int>(32);
field.SetValue(sb, newVal);
Test.Assert(sb.mA == 25);
Test.Assert(fieldVal2.Value.Get<int>() == 25);
field.SetValue(&sb, newVal);
Test.Assert(sb.mA == 32);
case 1: case 1:
Test.Assert(refP.Value.Get<String>() === "Struct B"); Test.Assert(fieldVal.Value.Get<String>() === "Struct B");
field.SetValue(&sb, "Struct C");
Test.Assert(sb.mB == "Struct C");
case 2: case 2:
StructC sc = .() { mA = 1.2f, mB = 2.3f };
Test.Assert(fieldVal.Value.Get<StructC>() == sc);
Test.Assert(fieldVal2.Value.Get<StructC>() == sc);
sc.mA += 100;
sc.mB += 100;
field.SetValue(&sb, sc);
Test.Assert(sb.mC.mA == 101.2f);
Test.Assert(sb.mC.mB == 102.3f);
sc.mA += 100;
sc.mB += 100;
field.SetValue(&sb, &sc);
Test.Assert(sb.mC.mA == 201.2f);
Test.Assert(sb.mC.mB == 202.3f);
sc.mA += 100;
sc.mB += 100;
Variant newVariant = Variant.Create(sc);
field.SetValue(&sb, newVariant);
Test.Assert(sb.mC.mA == 301.2f);
Test.Assert(sb.mC.mB == 302.3f);
sc.mA += 100;
sc.mB += 100;
newVariant.Dispose();
newVariant = Variant.Create(&sc);
field.SetValue(&sb, newVariant);
Test.Assert(sb.mC.mA == 401.2f);
Test.Assert(sb.mC.mB == 402.3f);
sc.mA += 100;
sc.mB += 100;
newVariant = Variant.CreateReference(typeof(StructC), &sc);
field.SetValue(&sb, newVariant);
Test.Assert(sb.mC.mA == 501.2f);
Test.Assert(sb.mC.mB == 502.3f);
case 3:
Test.FatalError(); Test.FatalError();
} }
fieldIdx++; fieldIdx++;