Support marshalling arrays of length 0 through BizInvoker
Such arrays will be marshalled with valid and unique pointers that can be compared but not read from or written to.
This commit is contained in:
parent
5b0fe947df
commit
66c19cfcb2
|
@ -86,6 +86,10 @@ namespace BizHawk.BizInvoke
|
|||
/// How far into a string pointer the first chair is.
|
||||
/// </summary>
|
||||
private static readonly int StringOffset;
|
||||
/// <summary>
|
||||
/// How far into a value array type element 0 is.
|
||||
/// </summary>
|
||||
private static readonly int ValueArrayElementOffset;
|
||||
|
||||
static BizInvoker()
|
||||
{
|
||||
|
@ -94,6 +98,7 @@ namespace BizHawk.BizInvoke
|
|||
ImplModuleBuilder = ImplAssemblyBuilder.DefineDynamicModule("BizInvokerModule");
|
||||
ClassFieldOffset = BizInvokerUtilities.ComputeClassFirstFieldOffset();
|
||||
StringOffset = BizInvokerUtilities.ComputeStringOffset();
|
||||
ValueArrayElementOffset = BizInvokerUtilities.ComputeValueArrayElementOffset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -546,9 +551,10 @@ namespace BizHawk.BizInvoke
|
|||
il.Emit(OpCodes.Ldarg, (short)idx);
|
||||
il.Emit(OpCodes.Dup);
|
||||
il.Emit(OpCodes.Stloc, loc);
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
il.Emit(OpCodes.Ldelema, et);
|
||||
il.Emit(OpCodes.Conv_I);
|
||||
il.Emit(OpCodes.Ldc_I4, ValueArrayElementOffset);
|
||||
il.Emit(OpCodes.Conv_I);
|
||||
il.Emit(OpCodes.Add);
|
||||
il.Emit(OpCodes.Br, end);
|
||||
|
||||
il.MarkLabel(isNull);
|
||||
|
|
|
@ -71,6 +71,48 @@ namespace BizHawk.BizInvoke
|
|||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the offset to the 0th element of an array of value types
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static int ComputeValueArrayElementOffset()
|
||||
{
|
||||
var arr = new int[4];
|
||||
int ret;
|
||||
fixed (int* p = arr)
|
||||
{
|
||||
U u = new(new U2(arr));
|
||||
ret = (int)((ulong)(UIntPtr) p - (ulong) u.First!.P);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the offset to the 0th element of an array of object types
|
||||
/// Slow, so cache it if you need it.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static int ComputeObjectArrayElementOffset()
|
||||
{
|
||||
var obj = new object[4];
|
||||
var method = new DynamicMethod("ComputeObjectArrayElementOffsetHelper", typeof(int), new[] { typeof(object[]) }, typeof(string).Module, true);
|
||||
var il = method.GetILGenerator();
|
||||
var local = il.DeclareLocal(typeof(object[]), true);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Stloc, local);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
il.Emit(OpCodes.Ldelema, typeof(object));
|
||||
il.Emit(OpCodes.Conv_I);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Conv_I);
|
||||
il.Emit(OpCodes.Sub);
|
||||
il.Emit(OpCodes.Conv_I4);
|
||||
il.Emit(OpCodes.Ret);
|
||||
var del = (Func<object[], int>)method.CreateDelegate(typeof(Func<object[], int>));
|
||||
return del(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the byte offset of a field relative to a pointer to the class instance.
|
||||
/// Slow, so cache it if you need it.
|
||||
|
|
Loading…
Reference in New Issue