diff --git a/Source/Engine/Engine/NativeInterop.Unmanaged.cs b/Source/Engine/Engine/NativeInterop.Unmanaged.cs index b40fa740a..2094a528f 100644 --- a/Source/Engine/Engine/NativeInterop.Unmanaged.cs +++ b/Source/Engine/Engine/NativeInterop.Unmanaged.cs @@ -857,36 +857,25 @@ namespace FlaxEngine.Interop } [UnmanagedCallersOnly] - internal static void FieldGetValueReference(ManagedHandle fieldOwnerHandle, ManagedHandle fieldHandle, IntPtr valuePtr) + internal static void FieldGetValueReference(ManagedHandle fieldOwnerHandle, ManagedHandle fieldHandle, int fieldOffset, IntPtr valuePtr) { object fieldOwner = fieldOwnerHandle.Target; + IntPtr fieldRef; +#if USE_AOT FieldHolder field = Unsafe.As(fieldHandle.Target); + fieldRef = IntPtr.Zero; + Debug.LogError("Not supported FieldGetValueReference"); +#else if (fieldOwner.GetType().IsValueType) { - ref IntPtr fieldRef = ref FieldHelper.GetValueTypeFieldReference(field.fieldOffset, ref fieldOwner); - Unsafe.Write(valuePtr.ToPointer(), fieldRef); + fieldRef = FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); } else { - ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference(field.fieldOffset, ref fieldOwner); - Unsafe.Write(valuePtr.ToPointer(), fieldRef); - } - } - - [UnmanagedCallersOnly] - internal static void FieldGetValueReferenceWithOffset(ManagedHandle fieldOwnerHandle, int fieldOffset, IntPtr valuePtr) - { - object fieldOwner = fieldOwnerHandle.Target; - if (fieldOwner.GetType().IsValueType) - { - ref IntPtr fieldRef = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); - Unsafe.Write(valuePtr.ToPointer(), fieldRef); - } - else - { - ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); - Unsafe.Write(valuePtr.ToPointer(), fieldRef); + fieldRef = FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); } +#endif + Unsafe.Write(valuePtr.ToPointer(), fieldRef); } [UnmanagedCallersOnly] diff --git a/Source/Engine/Engine/NativeInterop.cs b/Source/Engine/Engine/NativeInterop.cs index 094e8836b..2f74e421c 100644 --- a/Source/Engine/Engine/NativeInterop.cs +++ b/Source/Engine/Engine/NativeInterop.cs @@ -119,6 +119,7 @@ namespace FlaxEngine.Interop { } +#if !USE_AOT // Cache offsets to frequently accessed fields of FlaxEngine.Object private static int unmanagedPtrFieldOffset = IntPtr.Size + (Unsafe.Read((typeof(FlaxEngine.Object).GetField("__unmanagedPtr", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF); private static int internalIdFieldOffset = IntPtr.Size + (Unsafe.Read((typeof(FlaxEngine.Object).GetField("__internalId", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF); @@ -150,6 +151,7 @@ namespace FlaxEngine.Interop object obj = typeHolder.CreateScriptingObject(unmanagedPtr, idPtr); return ManagedHandle.Alloc(obj); } +#endif internal static void* NativeAlloc(int byteCount) { @@ -439,6 +441,23 @@ namespace FlaxEngine.Interop return fieldOffset; } +#if USE_AOT + /// + /// Helper utility to set field of the referenced value via reflection. + /// + internal static void SetReferenceTypeField(FieldInfo field, ref T fieldOwner, object fieldValue) + { + if (typeof(T).IsValueType) + { + // Value types need setting via boxed object to properly propagate value + object fieldOwnerBoxed = fieldOwner; + field.SetValue(fieldOwnerBoxed, fieldValue); + fieldOwner = (T)fieldOwnerBoxed; + } + else + field.SetValue(fieldOwner, fieldValue); + } +#else /// /// Returns a reference to the value of the field. /// @@ -465,6 +484,7 @@ namespace FlaxEngine.Interop byte* fieldPtr = (byte*)Unsafe.As(ref fieldOwner) + fieldOffset; return ref Unsafe.AsRef(fieldPtr); } +#endif } /// @@ -738,29 +758,49 @@ namespace FlaxEngine.Interop private static void ToManagedFieldPointerValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct { +#if USE_AOT + IntPtr fieldValue = Unsafe.Read(nativeFieldPtr.ToPointer()); + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#else ref IntPtr fieldValueRef = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); fieldValueRef = Unsafe.Read(nativeFieldPtr.ToPointer()); +#endif fieldSize = IntPtr.Size; } private static void ToManagedFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class { +#if USE_AOT + IntPtr fieldValue = Unsafe.Read(nativeFieldPtr.ToPointer()); + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#else ref IntPtr fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); fieldValueRef = Unsafe.Read(nativeFieldPtr.ToPointer()); +#endif fieldSize = IntPtr.Size; } private static void ToNativeFieldPointerValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct { - ref IntPtr fieldValueRef = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); - Unsafe.Write(nativeFieldPtr.ToPointer(), fieldValueRef); +#if USE_AOT + object boxed = field.GetValue(fieldOwner); + IntPtr fieldValue = new IntPtr(Pointer.Unbox(boxed)); +#else + IntPtr fieldValue = FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + Unsafe.Write(nativeFieldPtr.ToPointer(), fieldValue); fieldSize = IntPtr.Size; } private static void ToNativeFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class { - ref IntPtr fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); - Unsafe.Write(nativeFieldPtr.ToPointer(), fieldValueRef); +#if USE_AOT + object boxed = field.GetValue(fieldOwner); + IntPtr fieldValue = new IntPtr(Pointer.Unbox(boxed)); +#else + IntPtr fieldValue = FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + Unsafe.Write(nativeFieldPtr.ToPointer(), fieldValue); fieldSize = IntPtr.Size; } @@ -802,8 +842,15 @@ namespace FlaxEngine.Interop fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); } - ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToManaged(ref fieldValueRef, nativeFieldPtr, false); +#if USE_AOT + TField fieldValue = default; +#else + ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToManaged(ref fieldValue, nativeFieldPtr, false); +#if USE_AOT + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#endif } internal static void ToManagedFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class @@ -816,8 +863,15 @@ namespace FlaxEngine.Interop fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); } - ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToManaged(ref fieldValueRef, nativeFieldPtr, false); +#if USE_AOT + TField fieldValue = default; +#else + ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToManaged(ref fieldValue, nativeFieldPtr, false); +#if USE_AOT + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#endif } internal static void ToManagedFieldArrayValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct @@ -828,8 +882,15 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); - ref TField[] fieldValueRef = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToManaged(ref fieldValueRef, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + TField[] fieldValue = (TField[])field.GetValue(fieldOwner); +#else + ref TField[] fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#endif } internal static void ToManagedFieldArrayReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class @@ -840,8 +901,15 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); - ref TField[] fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToManaged(ref fieldValueRef, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + TField[] fieldValue = null; +#else + ref TField[] fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#endif } internal static void ToNativeFieldValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct @@ -855,11 +923,11 @@ namespace FlaxEngine.Interop } #if USE_AOT - TField fieldValueRef = (TField)field.GetValue(fieldOwner); + TField fieldValue = (TField)field.GetValue(fieldOwner); #else - ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); + ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); #endif - MarshalHelper.ToNative(ref fieldValueRef, nativeFieldPtr); + MarshalHelper.ToNative(ref fieldValue, nativeFieldPtr); } internal static void ToNativeFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class @@ -873,11 +941,11 @@ namespace FlaxEngine.Interop } #if USE_AOT - TField fieldValueRef = (TField)field.GetValue(fieldOwner); + TField fieldValue = (TField)field.GetValue(fieldOwner); #else - ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); + ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); #endif - MarshalHelper.ToNative(ref fieldValueRef, nativeFieldPtr); + MarshalHelper.ToNative(ref fieldValue, nativeFieldPtr); } } @@ -907,8 +975,15 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); - ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToManaged(ref fieldValueRef, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + TField fieldValue = null; +#else + ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#endif } internal static void ToManagedFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class @@ -918,8 +993,15 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); - ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToManaged(ref fieldValueRef, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + TField fieldValue = default; +#else + ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#endif } internal static void ToManagedFieldArrayValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct @@ -929,8 +1011,15 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); - ref TField[] fieldValueRef = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToManaged(ref fieldValueRef, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + TField[] fieldValue = null; +#else + ref TField[] fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#endif } internal static void ToManagedFieldArrayReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class @@ -940,8 +1029,15 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); - ref TField[] fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToManaged(ref fieldValueRef, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + TField[] fieldValue = null; +#else + ref TField[] fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); +#if USE_AOT + FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); +#endif } internal static void ToNativeFieldValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct @@ -951,8 +1047,12 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); - ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToNative(ref fieldValueRef, nativeFieldPtr); +#if USE_AOT + TField fieldValue = (TField)field.GetValue(fieldOwner); +#else + ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToNative(ref fieldValue, nativeFieldPtr); } internal static void ToNativeFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class @@ -962,8 +1062,12 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); - ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); - MarshalHelper.ToNative(ref fieldValueRef, nativeFieldPtr); +#if USE_AOT + TField fieldValue = (TField)field.GetValue(fieldOwner); +#else + ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); +#endif + MarshalHelper.ToNative(ref fieldValue, nativeFieldPtr); } } } @@ -1047,7 +1151,7 @@ namespace FlaxEngine.Interop var fields = MarshalHelper.marshallableFields; var offsets = MarshalHelper.marshallableFieldOffsets; var marshallers = MarshalHelper.toNativeFieldMarshallers; - for (int i = 0; i < MarshalHelper.marshallableFields.Length; i++) + for (int i = 0; i < fields.Length; i++) { marshallers[i](fields[i], offsets[i], ref managedValue, nativePtr, out int fieldSize); nativePtr += fieldSize; @@ -1309,11 +1413,13 @@ namespace FlaxEngine.Interop return RuntimeHelpers.GetUninitializedObject(wrappedType); } +#if !USE_AOT internal object CreateScriptingObject(IntPtr unmanagedPtr, IntPtr idPtr) { object obj = RuntimeHelpers.GetUninitializedObject(wrappedType); if (obj is Object) { + // TODO: use UnsafeAccessorAttribute on .NET 8 and use this path on all platforms (including non-Desktop, see MCore::ScriptingObject::CreateScriptingObject) { ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference(unmanagedPtrFieldOffset, ref obj); fieldRef = unmanagedPtr; @@ -1334,6 +1440,7 @@ namespace FlaxEngine.Interop return obj; } +#endif public static implicit operator Type(TypeHolder holder) => holder?.type; public bool Equals(TypeHolder other) => type == other.type; diff --git a/Source/Engine/Scripting/Runtime/DotNet.cpp b/Source/Engine/Scripting/Runtime/DotNet.cpp index 1d2dc1af1..a111ae337 100644 --- a/Source/Engine/Scripting/Runtime/DotNet.cpp +++ b/Source/Engine/Scripting/Runtime/DotNet.cpp @@ -186,7 +186,7 @@ void* GetStaticMethodPointer(const String& methodName); /// Calls the managed static method in NativeInterop class with given parameters. /// template -inline RetType CallStaticMethodByName(const String& methodName, Args... args) +FORCE_INLINE RetType CallStaticMethodByName(const String& methodName, Args... args) { typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...); return ((fun)GetStaticMethodPointer(methodName))(args...); @@ -196,7 +196,7 @@ inline RetType CallStaticMethodByName(const String& methodName, Args... args) /// Calls the managed static method with given parameters. /// template -inline RetType CallStaticMethod(void* methodPtr, Args... args) +FORCE_INLINE RetType CallStaticMethod(void* methodPtr, Args... args) { typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...); return ((fun)methodPtr)(args...); @@ -629,14 +629,33 @@ bool MCore::Type::IsReference(MType* type) void MCore::ScriptingObject::SetInternalValues(MClass* klass, MObject* object, void* unmanagedPtr, const Guid* id) { +#if PLATFORM_DESKTOP && !USE_MONO_AOT static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectSetInternalValues")); CallStaticMethod(ScriptingObjectSetInternalValuesPtr, object, unmanagedPtr, id); +#else + const MField* monoUnmanagedPtrField = klass->GetField("__unmanagedPtr"); + if (monoUnmanagedPtrField) + monoUnmanagedPtrField->SetValue(object, &unmanagedPtr); + const MField* monoIdField = klass->GetField("__internalId"); + if (id != nullptr && monoIdField) + monoIdField->SetValue(object, (void*)id); +#endif } MObject* MCore::ScriptingObject::CreateScriptingObject(MClass* klass, void* unmanagedPtr, const Guid* id) { +#if PLATFORM_DESKTOP && !USE_MONO_AOT static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectCreate")); return CallStaticMethod(ScriptingObjectSetInternalValuesPtr, klass->_handle, unmanagedPtr, id); +#else + MObject* object = MCore::Object::New(klass); + if (object) + { + MCore::ScriptingObject::SetInternalValues(klass, object, unmanagedPtr, id); + MCore::Object::Init(object); + } + return object; +#endif } const MAssembly::ClassesDictionary& MAssembly::GetClasses() const @@ -1253,8 +1272,8 @@ void MField::GetValue(MObject* instance, void* result) const void MField::GetValueReference(MObject* instance, void* result) const { - static void* FieldGetValueReferencePtr = GetStaticMethodPointer(TEXT("FieldGetValueReferenceWithOffset")); - CallStaticMethod(FieldGetValueReferencePtr, instance, _fieldOffset, result); + static void* FieldGetValueReferencePtr = GetStaticMethodPointer(TEXT("FieldGetValueReference")); + CallStaticMethod(FieldGetValueReferencePtr, instance, _handle, _fieldOffset, result); } MObject* MField::GetValueBoxed(MObject* instance) const diff --git a/Source/Engine/Scripting/ScriptingObject.cpp b/Source/Engine/Scripting/ScriptingObject.cpp index c32f37066..ac88db1bf 100644 --- a/Source/Engine/Scripting/ScriptingObject.cpp +++ b/Source/Engine/Scripting/ScriptingObject.cpp @@ -241,7 +241,7 @@ ScriptingObject* ScriptingObject::ToNative(MObject* obj) #if USE_CSHARP if (obj) { -#if USE_MONO +#if USE_MONO || USE_MONO_AOT const auto ptrField = MCore::Object::GetClass(obj)->GetField(ScriptingObject_unmanagedPtr); CHECK_RETURN(ptrField, nullptr); ptrField->GetValue(obj, &ptr); diff --git a/Source/Engine/UI/UICanvas.cpp b/Source/Engine/UI/UICanvas.cpp index b3318c75c..a83d61f7a 100644 --- a/Source/Engine/UI/UICanvas.cpp +++ b/Source/Engine/UI/UICanvas.cpp @@ -56,6 +56,7 @@ UICanvas::UICanvas(const SpawnParams& params) UICanvas_EndPlay = mclass->GetMethod("EndPlay"); UICanvas_ParentChanged = mclass->GetMethod("ParentChanged"); UICanvas_Serialize = mclass->GetMethod("Serialize"); + Platform::MemoryBarrier(); } #endif }