Fix scripting interop in AOT mode to use reflection-based field access
This commit is contained in:
@@ -857,36 +857,25 @@ namespace FlaxEngine.Interop
|
|||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[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;
|
object fieldOwner = fieldOwnerHandle.Target;
|
||||||
|
IntPtr fieldRef;
|
||||||
|
#if USE_AOT
|
||||||
FieldHolder field = Unsafe.As<FieldHolder>(fieldHandle.Target);
|
FieldHolder field = Unsafe.As<FieldHolder>(fieldHandle.Target);
|
||||||
|
fieldRef = IntPtr.Zero;
|
||||||
|
Debug.LogError("Not supported FieldGetValueReference");
|
||||||
|
#else
|
||||||
if (fieldOwner.GetType().IsValueType)
|
if (fieldOwner.GetType().IsValueType)
|
||||||
{
|
{
|
||||||
ref IntPtr fieldRef = ref FieldHelper.GetValueTypeFieldReference<object, IntPtr>(field.fieldOffset, ref fieldOwner);
|
fieldRef = FieldHelper.GetValueTypeFieldReference<object, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
Unsafe.Write<IntPtr>(valuePtr.ToPointer(), fieldRef);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference<object, IntPtr>(field.fieldOffset, ref fieldOwner);
|
fieldRef = FieldHelper.GetReferenceTypeFieldReference<object, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
Unsafe.Write<IntPtr>(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<object, IntPtr>(fieldOffset, ref fieldOwner);
|
|
||||||
Unsafe.Write<IntPtr>(valuePtr.ToPointer(), fieldRef);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference<object, IntPtr>(fieldOffset, ref fieldOwner);
|
|
||||||
Unsafe.Write<IntPtr>(valuePtr.ToPointer(), fieldRef);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
Unsafe.Write<IntPtr>(valuePtr.ToPointer(), fieldRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ namespace FlaxEngine.Interop
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !USE_AOT
|
||||||
// Cache offsets to frequently accessed fields of FlaxEngine.Object
|
// Cache offsets to frequently accessed fields of FlaxEngine.Object
|
||||||
private static int unmanagedPtrFieldOffset = IntPtr.Size + (Unsafe.Read<int>((typeof(FlaxEngine.Object).GetField("__unmanagedPtr", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF);
|
private static int unmanagedPtrFieldOffset = IntPtr.Size + (Unsafe.Read<int>((typeof(FlaxEngine.Object).GetField("__unmanagedPtr", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF);
|
||||||
private static int internalIdFieldOffset = IntPtr.Size + (Unsafe.Read<int>((typeof(FlaxEngine.Object).GetField("__internalId", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF);
|
private static int internalIdFieldOffset = IntPtr.Size + (Unsafe.Read<int>((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);
|
object obj = typeHolder.CreateScriptingObject(unmanagedPtr, idPtr);
|
||||||
return ManagedHandle.Alloc(obj);
|
return ManagedHandle.Alloc(obj);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
internal static void* NativeAlloc(int byteCount)
|
internal static void* NativeAlloc(int byteCount)
|
||||||
{
|
{
|
||||||
@@ -439,6 +441,23 @@ namespace FlaxEngine.Interop
|
|||||||
return fieldOffset;
|
return fieldOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_AOT
|
||||||
|
/// <summary>
|
||||||
|
/// Helper utility to set field of the referenced value via reflection.
|
||||||
|
/// </summary>
|
||||||
|
internal static void SetReferenceTypeField<T>(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
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a reference to the value of the field.
|
/// Returns a reference to the value of the field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -465,6 +484,7 @@ namespace FlaxEngine.Interop
|
|||||||
byte* fieldPtr = (byte*)Unsafe.As<T, IntPtr>(ref fieldOwner) + fieldOffset;
|
byte* fieldPtr = (byte*)Unsafe.As<T, IntPtr>(ref fieldOwner) + fieldOffset;
|
||||||
return ref Unsafe.AsRef<TField>(fieldPtr);
|
return ref Unsafe.AsRef<TField>(fieldPtr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -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
|
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<IntPtr>(nativeFieldPtr.ToPointer());
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#else
|
||||||
ref IntPtr fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
ref IntPtr fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
fieldValueRef = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
fieldValueRef = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
||||||
|
#endif
|
||||||
fieldSize = IntPtr.Size;
|
fieldSize = IntPtr.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ToManagedFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
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<IntPtr>(nativeFieldPtr.ToPointer());
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#else
|
||||||
ref IntPtr fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
ref IntPtr fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
fieldValueRef = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
fieldValueRef = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
||||||
|
#endif
|
||||||
fieldSize = IntPtr.Size;
|
fieldSize = IntPtr.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ToNativeFieldPointerValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
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<T, IntPtr>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
Unsafe.Write<IntPtr>(nativeFieldPtr.ToPointer(), fieldValueRef);
|
object boxed = field.GetValue(fieldOwner);
|
||||||
|
IntPtr fieldValue = new IntPtr(Pointer.Unbox(boxed));
|
||||||
|
#else
|
||||||
|
IntPtr fieldValue = FieldHelper.GetValueTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
Unsafe.Write<IntPtr>(nativeFieldPtr.ToPointer(), fieldValue);
|
||||||
fieldSize = IntPtr.Size;
|
fieldSize = IntPtr.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ToNativeFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
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<T, IntPtr>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
Unsafe.Write<IntPtr>(nativeFieldPtr.ToPointer(), fieldValueRef);
|
object boxed = field.GetValue(fieldOwner);
|
||||||
|
IntPtr fieldValue = new IntPtr(Pointer.Unbox(boxed));
|
||||||
|
#else
|
||||||
|
IntPtr fieldValue = FieldHelper.GetReferenceTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
Unsafe.Write<IntPtr>(nativeFieldPtr.ToPointer(), fieldValue);
|
||||||
fieldSize = IntPtr.Size;
|
fieldSize = IntPtr.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,8 +842,15 @@ namespace FlaxEngine.Interop
|
|||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToManaged(ref fieldValueRef, nativeFieldPtr, false);
|
TField fieldValue = default;
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.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
|
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();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToManaged(ref fieldValueRef, nativeFieldPtr, false);
|
TField fieldValue = default;
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.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
|
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);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField[] fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField[]>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField[] fieldValue = (TField[])field.GetValue(fieldOwner);
|
||||||
|
#else
|
||||||
|
ref TField[] fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField[]>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(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
|
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);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField[] fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField[]>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField[] fieldValue = null;
|
||||||
|
#else
|
||||||
|
ref TField[] fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField[]>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(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
|
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
|
#if USE_AOT
|
||||||
TField fieldValueRef = (TField)field.GetValue(fieldOwner);
|
TField fieldValue = (TField)field.GetValue(fieldOwner);
|
||||||
#else
|
#else
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
#endif
|
#endif
|
||||||
MarshalHelper<TField>.ToNative(ref fieldValueRef, nativeFieldPtr);
|
MarshalHelper<TField>.ToNative(ref fieldValue, nativeFieldPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToNativeFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
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
|
#if USE_AOT
|
||||||
TField fieldValueRef = (TField)field.GetValue(fieldOwner);
|
TField fieldValue = (TField)field.GetValue(fieldOwner);
|
||||||
#else
|
#else
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
#endif
|
#endif
|
||||||
MarshalHelper<TField>.ToNative(ref fieldValueRef, nativeFieldPtr);
|
MarshalHelper<TField>.ToNative(ref fieldValue, nativeFieldPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -907,8 +975,15 @@ namespace FlaxEngine.Interop
|
|||||||
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField fieldValue = null;
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(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
|
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);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField fieldValue = default;
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(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
|
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);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField[] fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField[]>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField[] fieldValue = null;
|
||||||
|
#else
|
||||||
|
ref TField[] fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField[]>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(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
|
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);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField[] fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField[]>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField[] fieldValue = null;
|
||||||
|
#else
|
||||||
|
ref TField[] fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField[]>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(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
|
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);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToNative(ref fieldValueRef, nativeFieldPtr);
|
TField fieldValue = (TField)field.GetValue(fieldOwner);
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToNative(ref fieldValue, nativeFieldPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToNativeFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
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);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToNative(ref fieldValueRef, nativeFieldPtr);
|
TField fieldValue = (TField)field.GetValue(fieldOwner);
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToNative(ref fieldValue, nativeFieldPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1047,7 +1151,7 @@ namespace FlaxEngine.Interop
|
|||||||
var fields = MarshalHelper<T>.marshallableFields;
|
var fields = MarshalHelper<T>.marshallableFields;
|
||||||
var offsets = MarshalHelper<T>.marshallableFieldOffsets;
|
var offsets = MarshalHelper<T>.marshallableFieldOffsets;
|
||||||
var marshallers = MarshalHelper<T>.toNativeFieldMarshallers;
|
var marshallers = MarshalHelper<T>.toNativeFieldMarshallers;
|
||||||
for (int i = 0; i < MarshalHelper<T>.marshallableFields.Length; i++)
|
for (int i = 0; i < fields.Length; i++)
|
||||||
{
|
{
|
||||||
marshallers[i](fields[i], offsets[i], ref managedValue, nativePtr, out int fieldSize);
|
marshallers[i](fields[i], offsets[i], ref managedValue, nativePtr, out int fieldSize);
|
||||||
nativePtr += fieldSize;
|
nativePtr += fieldSize;
|
||||||
@@ -1309,11 +1413,13 @@ namespace FlaxEngine.Interop
|
|||||||
return RuntimeHelpers.GetUninitializedObject(wrappedType);
|
return RuntimeHelpers.GetUninitializedObject(wrappedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !USE_AOT
|
||||||
internal object CreateScriptingObject(IntPtr unmanagedPtr, IntPtr idPtr)
|
internal object CreateScriptingObject(IntPtr unmanagedPtr, IntPtr idPtr)
|
||||||
{
|
{
|
||||||
object obj = RuntimeHelpers.GetUninitializedObject(wrappedType);
|
object obj = RuntimeHelpers.GetUninitializedObject(wrappedType);
|
||||||
if (obj is Object)
|
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<IntPtr>(unmanagedPtrFieldOffset, ref obj);
|
ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference<IntPtr>(unmanagedPtrFieldOffset, ref obj);
|
||||||
fieldRef = unmanagedPtr;
|
fieldRef = unmanagedPtr;
|
||||||
@@ -1334,6 +1440,7 @@ namespace FlaxEngine.Interop
|
|||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static implicit operator Type(TypeHolder holder) => holder?.type;
|
public static implicit operator Type(TypeHolder holder) => holder?.type;
|
||||||
public bool Equals(TypeHolder other) => type == other.type;
|
public bool Equals(TypeHolder other) => type == other.type;
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ void* GetStaticMethodPointer(const String& methodName);
|
|||||||
/// Calls the managed static method in NativeInterop class with given parameters.
|
/// Calls the managed static method in NativeInterop class with given parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
template<typename RetType, typename... Args>
|
template<typename RetType, typename... Args>
|
||||||
inline RetType CallStaticMethodByName(const String& methodName, Args... args)
|
FORCE_INLINE RetType CallStaticMethodByName(const String& methodName, Args... args)
|
||||||
{
|
{
|
||||||
typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...);
|
typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...);
|
||||||
return ((fun)GetStaticMethodPointer(methodName))(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.
|
/// Calls the managed static method with given parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
template<typename RetType, typename... Args>
|
template<typename RetType, typename... Args>
|
||||||
inline RetType CallStaticMethod(void* methodPtr, Args... args)
|
FORCE_INLINE RetType CallStaticMethod(void* methodPtr, Args... args)
|
||||||
{
|
{
|
||||||
typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...);
|
typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...);
|
||||||
return ((fun)methodPtr)(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)
|
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"));
|
static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectSetInternalValues"));
|
||||||
CallStaticMethod<void, MObject*, void*, const Guid*>(ScriptingObjectSetInternalValuesPtr, object, unmanagedPtr, id);
|
CallStaticMethod<void, MObject*, void*, const Guid*>(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)
|
MObject* MCore::ScriptingObject::CreateScriptingObject(MClass* klass, void* unmanagedPtr, const Guid* id)
|
||||||
{
|
{
|
||||||
|
#if PLATFORM_DESKTOP && !USE_MONO_AOT
|
||||||
static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectCreate"));
|
static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectCreate"));
|
||||||
return CallStaticMethod<MObject*, void*, void*, const Guid*>(ScriptingObjectSetInternalValuesPtr, klass->_handle, unmanagedPtr, id);
|
return CallStaticMethod<MObject*, void*, void*, const Guid*>(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
|
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
|
void MField::GetValueReference(MObject* instance, void* result) const
|
||||||
{
|
{
|
||||||
static void* FieldGetValueReferencePtr = GetStaticMethodPointer(TEXT("FieldGetValueReferenceWithOffset"));
|
static void* FieldGetValueReferencePtr = GetStaticMethodPointer(TEXT("FieldGetValueReference"));
|
||||||
CallStaticMethod<void, void*, int, void*>(FieldGetValueReferencePtr, instance, _fieldOffset, result);
|
CallStaticMethod<void, void*, void*, int, void*>(FieldGetValueReferencePtr, instance, _handle, _fieldOffset, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
MObject* MField::GetValueBoxed(MObject* instance) const
|
MObject* MField::GetValueBoxed(MObject* instance) const
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ ScriptingObject* ScriptingObject::ToNative(MObject* obj)
|
|||||||
#if USE_CSHARP
|
#if USE_CSHARP
|
||||||
if (obj)
|
if (obj)
|
||||||
{
|
{
|
||||||
#if USE_MONO
|
#if USE_MONO || USE_MONO_AOT
|
||||||
const auto ptrField = MCore::Object::GetClass(obj)->GetField(ScriptingObject_unmanagedPtr);
|
const auto ptrField = MCore::Object::GetClass(obj)->GetField(ScriptingObject_unmanagedPtr);
|
||||||
CHECK_RETURN(ptrField, nullptr);
|
CHECK_RETURN(ptrField, nullptr);
|
||||||
ptrField->GetValue(obj, &ptr);
|
ptrField->GetValue(obj, &ptr);
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ UICanvas::UICanvas(const SpawnParams& params)
|
|||||||
UICanvas_EndPlay = mclass->GetMethod("EndPlay");
|
UICanvas_EndPlay = mclass->GetMethod("EndPlay");
|
||||||
UICanvas_ParentChanged = mclass->GetMethod("ParentChanged");
|
UICanvas_ParentChanged = mclass->GetMethod("ParentChanged");
|
||||||
UICanvas_Serialize = mclass->GetMethod("Serialize");
|
UICanvas_Serialize = mclass->GetMethod("Serialize");
|
||||||
|
Platform::MemoryBarrier();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user