Refactor managed array unboxing to handle case of C# array passes as object

#1415
This commit is contained in:
Wojtek Figat
2023-09-20 14:17:11 +02:00
parent 5c5c64cf76
commit 8bd6649510
6 changed files with 33 additions and 2 deletions

View File

@@ -559,6 +559,19 @@ namespace FlaxEngine.Interop
return managedArray.Pointer; return managedArray.Pointer;
} }
[UnmanagedCallersOnly]
internal static IntPtr GetArray(ManagedHandle handle)
{
if (!handle.IsAllocated)
return IntPtr.Zero;
object value = handle.Target;
if (value is ManagedArray)
return (IntPtr)handle;
if (value is Array)
return Invoker.MarshalReturnValueGeneric(value.GetType(), value);
return IntPtr.Zero;
}
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
internal static int GetArrayLength(ManagedHandle arrayHandle) internal static int GetArrayLength(ManagedHandle arrayHandle)
{ {

View File

@@ -85,6 +85,7 @@ public:
static MClass* GetClass(MClass* elementKlass); static MClass* GetClass(MClass* elementKlass);
static int32 GetLength(const MArray* obj); static int32 GetLength(const MArray* obj);
static void* GetAddress(const MArray* obj); static void* GetAddress(const MArray* obj);
static MArray* Unbox(MObject* obj);
template<typename T> template<typename T>
FORCE_INLINE static T* GetAddress(const MArray* obj) FORCE_INLINE static T* GetAddress(const MArray* obj)

View File

@@ -363,11 +363,12 @@ struct MConverter<Array<T>>
void Unbox(Array<T>& result, MObject* data) void Unbox(Array<T>& result, MObject* data)
{ {
const int32 length = data ? MCore::Array::GetLength((MArray*)data) : 0; MArray* array = MCore::Array::Unbox(data);
const int32 length = array ? MCore::Array::GetLength(array) : 0;
result.Resize(length); result.Resize(length);
MConverter<T> converter; MConverter<T> converter;
Span<T> resultSpan(result.Get(), length); Span<T> resultSpan(result.Get(), length);
converter.ToNativeArray(resultSpan, (MArray*)data); converter.ToNativeArray(resultSpan, array);
} }
}; };

View File

@@ -408,6 +408,12 @@ void* MCore::Array::GetAddress(const MArray* obj)
return CallStaticMethod<void*, void*>(GetArrayPointerPtr, (void*)obj); return CallStaticMethod<void*, void*>(GetArrayPointerPtr, (void*)obj);
} }
MArray* MCore::Array::Unbox(MObject* obj)
{
static void* GetArrayPtr = GetStaticMethodPointer(TEXT("GetArray"));
return (MArray*)CallStaticMethod<void*, void*>(GetArrayPtr, (void*)obj);
}
MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned) MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned)
{ {
ASSERT(obj); ASSERT(obj);

View File

@@ -804,6 +804,11 @@ void* MCore::Array::GetAddress(const MArray* obj)
return mono_array_addr_with_size((MonoArray*)obj, 0, 0); return mono_array_addr_with_size((MonoArray*)obj, 0, 0);
} }
MArray* MCore::Array::Unbox(MObject* obj)
{
return (MArray*)obj;
}
MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned) MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned)
{ {
return mono_gchandle_new(obj, pinned); return mono_gchandle_new(obj, pinned);

View File

@@ -141,6 +141,11 @@ void* MCore::Array::GetAddress(const MArray* obj)
return nullptr; return nullptr;
} }
MArray* MCore::Array::Unbox(MObject* obj)
{
return nullptr;
}
MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned) MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned)
{ {
return (MGCHandle)(uintptr)obj; return (MGCHandle)(uintptr)obj;