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.
|
/// How far into a string pointer the first chair is.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly int StringOffset;
|
private static readonly int StringOffset;
|
||||||
|
/// <summary>
|
||||||
|
/// How far into a value array type element 0 is.
|
||||||
|
/// </summary>
|
||||||
|
private static readonly int ValueArrayElementOffset;
|
||||||
|
|
||||||
static BizInvoker()
|
static BizInvoker()
|
||||||
{
|
{
|
||||||
|
@ -94,6 +98,7 @@ namespace BizHawk.BizInvoke
|
||||||
ImplModuleBuilder = ImplAssemblyBuilder.DefineDynamicModule("BizInvokerModule");
|
ImplModuleBuilder = ImplAssemblyBuilder.DefineDynamicModule("BizInvokerModule");
|
||||||
ClassFieldOffset = BizInvokerUtilities.ComputeClassFirstFieldOffset();
|
ClassFieldOffset = BizInvokerUtilities.ComputeClassFirstFieldOffset();
|
||||||
StringOffset = BizInvokerUtilities.ComputeStringOffset();
|
StringOffset = BizInvokerUtilities.ComputeStringOffset();
|
||||||
|
ValueArrayElementOffset = BizInvokerUtilities.ComputeValueArrayElementOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -546,9 +551,10 @@ namespace BizHawk.BizInvoke
|
||||||
il.Emit(OpCodes.Ldarg, (short)idx);
|
il.Emit(OpCodes.Ldarg, (short)idx);
|
||||||
il.Emit(OpCodes.Dup);
|
il.Emit(OpCodes.Dup);
|
||||||
il.Emit(OpCodes.Stloc, loc);
|
il.Emit(OpCodes.Stloc, loc);
|
||||||
il.Emit(OpCodes.Ldc_I4_0);
|
|
||||||
il.Emit(OpCodes.Ldelema, et);
|
|
||||||
il.Emit(OpCodes.Conv_I);
|
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.Emit(OpCodes.Br, end);
|
||||||
|
|
||||||
il.MarkLabel(isNull);
|
il.MarkLabel(isNull);
|
||||||
|
|
|
@ -71,6 +71,48 @@ namespace BizHawk.BizInvoke
|
||||||
return ret;
|
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>
|
/// <summary>
|
||||||
/// Compute the byte offset of a field relative to a pointer to the class instance.
|
/// Compute the byte offset of a field relative to a pointer to the class instance.
|
||||||
/// Slow, so cache it if you need it.
|
/// Slow, so cache it if you need it.
|
||||||
|
|
Loading…
Reference in New Issue