Fix managed array element marshalling with strings

This commit is contained in:
2022-11-29 18:40:11 +02:00
parent 676d87129c
commit cc7655d804

View File

@@ -765,31 +765,31 @@ namespace FlaxEngine
return FindType(internalAssemblyQualifiedName);
}
private static IntPtr EnsureAlignment(IntPtr ptr, int alignment)
{
if (ptr % alignment != 0)
ptr = IntPtr.Add(ptr, alignment - (int)(ptr % alignment));
return ptr;
}
internal static void MarshalFromObject(object obj, Type objectType, ref IntPtr targetPtr)
{
void EnsureAlignment(ref IntPtr ptr, int alignment)
{
int paddingSize = (int)(ptr.ToInt64() % alignment);
if (paddingSize != 0)
ptr = IntPtr.Add(ptr, alignment - paddingSize);
}
int readOffset = 0;
if (objectType == typeof(IntPtr))
{
EnsureAlignment(ref targetPtr, IntPtr.Size);
targetPtr = EnsureAlignment(targetPtr, IntPtr.Size);
Marshal.WriteIntPtr(targetPtr, (IntPtr)obj);
readOffset = IntPtr.Size;
}
else if (objectType == typeof(byte))
{
EnsureAlignment(ref targetPtr, sizeof(byte));
targetPtr = EnsureAlignment(targetPtr, sizeof(byte));
Marshal.WriteByte(targetPtr, (byte)obj);
readOffset = sizeof(byte);
}
else if (objectType == typeof(bool))
{
EnsureAlignment(ref targetPtr, sizeof(byte));
targetPtr = EnsureAlignment(targetPtr, sizeof(byte));
Marshal.WriteByte(targetPtr, ((bool)obj) ? (byte)1 : (byte)0);
readOffset = sizeof(byte);
}
@@ -799,25 +799,25 @@ namespace FlaxEngine
}
else if (objectType == typeof(int) || objectType.Name == "Int32&")
{
EnsureAlignment(ref targetPtr, sizeof(int));
targetPtr = EnsureAlignment(targetPtr, sizeof(int));
Marshal.WriteInt32(targetPtr, (int)obj);
readOffset = sizeof(int);
}
else if (objectType == typeof(long))
{
EnsureAlignment(ref targetPtr, sizeof(long));
targetPtr = EnsureAlignment(targetPtr, sizeof(long));
Marshal.WriteInt64(targetPtr, (long)obj);
readOffset = sizeof(long);
}
else if (objectType == typeof(short))
{
EnsureAlignment(ref targetPtr, sizeof(short));
targetPtr = EnsureAlignment(targetPtr, sizeof(short));
Marshal.WriteInt16(targetPtr, (short)obj);
readOffset = sizeof(short);
}
else if (objectType == typeof(string))
{
EnsureAlignment(ref targetPtr, IntPtr.Size);
targetPtr = EnsureAlignment(targetPtr, IntPtr.Size);
IntPtr strPtr = ManagedString.ToNative(obj as string);
Marshal.WriteIntPtr(targetPtr, strPtr);
readOffset = IntPtr.Size;
@@ -828,7 +828,7 @@ namespace FlaxEngine
{
if (objectType.IsPointer)
{
EnsureAlignment(ref targetPtr, IntPtr.Size);
targetPtr = EnsureAlignment(targetPtr, IntPtr.Size);
var unboxed = Pointer.Unbox(obj);
if (unboxed == null)
Marshal.WriteIntPtr(targetPtr, IntPtr.Zero);
@@ -840,7 +840,7 @@ namespace FlaxEngine
}
else
{
EnsureAlignment(ref targetPtr, IntPtr.Size);
targetPtr = EnsureAlignment(targetPtr, IntPtr.Size);
Marshal.WriteIntPtr(targetPtr, obj != null ? GCHandle.ToIntPtr(GCHandle.Alloc(obj, GCHandleType.Weak)) : IntPtr.Zero);
readOffset = IntPtr.Size;
}
@@ -913,22 +913,16 @@ namespace FlaxEngine
if (ptr == IntPtr.Zero)
return null;
Type elementType = type.GetElementType();
ManagedArray arr = (ManagedArray)GCHandle.FromIntPtr(ptr).Target;
if (type.Name == "Type[]")
{
var intPtrArr = arr.array as IntPtr[];
Type[] typeArr = intPtrArr.Select(x => GCHandle.FromIntPtr(x).Target).OfType<Type>().ToArray();
return typeArr;
}
if (arr.array.GetType().GetElementType() == typeof(string))
{
string[] strs = new string[arr.Length];
IntPtr[] ptrs = ((IntPtr[])arr.array);
for (int i = 0; i < strs.Length; i++)
strs[i] = ManagedString.ToManaged(ptrs[i]);
return strs;
}
return arr.array;
if (arr.array.GetType().GetElementType() == elementType)
return arr.array;
IntPtr[] ptrs = (IntPtr[])arr.array;
Array marshalledArray = Array.CreateInstance(elementType, ptrs.Length);
for (int i = 0; i < marshalledArray.Length; i++)
marshalledArray.SetValue(MarshalToObject(elementType, ptrs[i], out _), i);
return marshalledArray;
}
else if (type.IsClass)
{
@@ -937,7 +931,6 @@ namespace FlaxEngine
return null;
var obj = GCHandle.FromIntPtr(ptr).Target;
Assert.IsTrue(obj == null || obj.GetType() == type || obj.GetType().IsSubclassOf(type) || (obj.GetType().FullName == "System.RuntimeType" && type == typeof(Type)));
return obj;
}
else if (type.IsValueType)
@@ -956,18 +949,6 @@ namespace FlaxEngine
fieldValue = MarshalToObject(field.FieldType, Marshal.ReadIntPtr(fieldPtr), out size);
else
{
void EnsureAlignment(ref IntPtr ptr2, ref int readSize, int alignment)
{
int paddingSize = (int)(ptr2.ToInt64() % alignment);
if (paddingSize != 0)
{
int offset = alignment - paddingSize;
ptr2 = IntPtr.Add(ptr2, offset);
readSize += offset;
}
}
int fieldReadSize = 0;
int fieldSize;
Type fieldType = field.FieldType;
if (field.FieldType.IsEnum)
@@ -981,7 +962,7 @@ namespace FlaxEngine
fieldSize = IntPtr.Size;
else
fieldSize = Marshal.SizeOf(fieldType);
EnsureAlignment(ref fieldPtr, ref fieldReadSize, fieldSize);
fieldPtr = EnsureAlignment(fieldPtr, fieldSize);
fieldValue = MarshalToObject(field.FieldType, fieldPtr, out size);
}