// Copyright (c) Wojciech Figat. All rights reserved. #pragma once #include "MTypes.h" #include "MClass.h" #include "MCore.h" #include "Engine/Core/Types/StringView.h" #include "Engine/Core/Types/DataContainer.h" #include "Engine/Core/Types/Variant.h" #include "Engine/Core/Collections/Array.h" #include "Engine/Scripting/ScriptingObject.h" #if USE_CSHARP /*static_assert(TIsPODType::Value, "int not pod type?"); static_assert(TIsPODType::Value, "Float3 not pod type?"); static_assert(!TIsPODType::Value, "ScriptingObject not pod type?"); static_assert(TIsPODType::Value, "Char not pod type?"); static_assert(TIsPODType::Value, "char not pod type?");*/ struct Version; class CultureInfo; template class BitArray; namespace MUtils { extern FLAXENGINE_API StringView ToString(MString* str); extern FLAXENGINE_API StringAnsi ToStringAnsi(MString* str); extern FLAXENGINE_API void ToString(MString* str, String& result); extern FLAXENGINE_API void ToString(MString* str, StringView& result); extern FLAXENGINE_API void ToString(MString* str, Variant& result); extern FLAXENGINE_API void ToString(MString* str, StringAnsi& result); extern FLAXENGINE_API MString* ToString(const char* str); extern FLAXENGINE_API MString* ToString(const StringAnsi& str); extern FLAXENGINE_API MString* ToString(const String& str); extern FLAXENGINE_API MString* ToString(const String& str, MDomain* domain); extern FLAXENGINE_API MString* ToString(const StringAnsiView& str); extern FLAXENGINE_API MString* ToString(const StringView& str); extern FLAXENGINE_API MString* ToString(const StringView& str, MDomain* domain); extern FLAXENGINE_API ScriptingTypeHandle UnboxScriptingTypeHandle(MTypeObject* value); extern FLAXENGINE_API MTypeObject* BoxScriptingTypeHandle(const ScriptingTypeHandle& value); extern FLAXENGINE_API VariantType UnboxVariantType(MType* type); extern FLAXENGINE_API MTypeObject* BoxVariantType(const VariantType& value); extern FLAXENGINE_API Variant UnboxVariant(MObject* value, bool releaseHandle = false); extern FLAXENGINE_API MObject* BoxVariant(const Variant& value); } // Converter for data of type T between managed and unmanaged world template struct MConverter { MObject* Box(const T& data, const MClass* klass); void Unbox(T& result, MObject* data); /*template void ToManaged(U& result, const T& data); template void ToNative(T& result, const U& data); void ToManaged(MObject*& result, const T& data); void ToNative(T& result, const MObject*& data);*/ void FreeManaged(MObject* data); void ToManagedArray(MArray* result, const Span& data); void ToNativeArray(Span& result, const MArray* data); void FreeManagedArray(MArray* array); }; // Simple array used to pass arrays of blittable data between managed and unmanaged side. template struct NativeArray { T* data; int32 length; FORCE_INLINE operator T*() const { return data; } FORCE_INLINE Span ToSpan() const { return Span(data, length); } }; #if USE_NETCORE // Special case for boolean values, the handles are fixed and should not be removed template<> struct MConverter { MObject* Box(const bool& data, const MClass* klass) { return MCore::Object::Box((void*)&data, klass); } void Unbox(bool& result, MObject* data) { if (data) MCore::Object::Unbox(data, &result); } void ToManaged(bool& result, const bool& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(bool& result, const bool& data) { PLATFORM_DEBUG_BREAK; // FIXME } void FreeManaged(MObject* data) { } void ToManagedArray(MArray* result, const Span& data) { Platform::MemoryCopy(MCore::Array::GetAddress(result), data.Get(), data.Length() * sizeof(bool)); } void ToNativeArray(Span& result, const MArray* data) { Platform::MemoryCopy(result.Get(), MCore::Array::GetAddress(data), result.Length() * sizeof(bool)); } void FreeManagedArray(MArray* array) { MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; #endif // Converter for POD types (that can use raw memory copy). template struct MConverter, TNot::Type>>>::Value>::Type> { MObject* Box(const T& data, const MClass* klass) { return MCore::Object::Box((void*)&data, klass); } void Unbox(T& result, MObject* data) { if (data) MCore::Object::Unbox(data, &result); } void ToManaged(T& result, const T& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(T& result, const T& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToManagedArray(MArray* result, const Span& data) { Platform::MemoryCopy(MCore::Array::GetAddress(result), data.Get(), data.Length() * sizeof(T)); } void ToNativeArray(Span& result, const MArray* data) { Platform::MemoryCopy(result.Get(), MCore::Array::GetAddress(data), result.Length() * sizeof(T)); } void FreeManaged(MObject* data) { MCore::GCHandle::Free(*(MGCHandle*)&data); } void FreeManagedArray(MArray* array) { MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // Converter for String. template<> struct MConverter { MObject* Box(const String& data, const MClass* klass) { /*#if USE_NETCORE MString* str = MUtils::ToString(data); return MCore::Object::Box(str, klass); #else*/ return (MObject*)MUtils::ToString(data); //#endif } void Unbox(String& result, MObject* data) { /*#if USE_NETCORE MString* str = (MString*)MCore::Object::Unbox(data); result = MUtils::ToString(str); #else*/ result = MUtils::ToString((MString*)data); //#endif } void ToManaged(String& result, const String& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(String& result, const String& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToManagedArray(MArray* result, const Span& data) { if (data.Length() == 0) return; MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*)); for (int32 i = 0; i < data.Length(); i++) objects[i] = (MObject*)MUtils::ToString(data.Get()[i]); MCore::GC::WriteArrayRef(result, Span(objects, data.Length())); Allocator::Free(objects); } void ToNativeArray(Span& result, const MArray* data) { MString** dataPtr = MCore::Array::GetAddress(data); for (int32 i = 0; i < result.Length(); i++) MUtils::ToString(dataPtr[i], result.Get()[i]); } void FreeManaged(MObject* data) { //MString* str = (MString*)MCore::Object::Unbox(data); //MCore::GCHandle::Free(*(MGCHandle*)&str); MCore::String::Free((MString*)data); } void FreeManagedArray(MArray* array) { MString** dataPtr = MCore::Array::GetAddress(array); auto length = MCore::Array::GetLength(array); for (int32 i = 0; i < length; i++) MCore::String::Free(dataPtr[i]); MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // Converter for StringAnsi. template<> struct MConverter { MObject* Box(const StringAnsi& data, const MClass* klass) { return (MObject*)MUtils::ToString(data); } void Unbox(StringAnsi& result, MObject* data) { result = MUtils::ToStringAnsi((MString*)data); } void ToManaged(StringAnsi& result, const StringAnsi& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(StringAnsi& result, const StringAnsi& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToManagedArray(MArray* result, const Span& data) { if (data.Length() == 0) return; auto* objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*)); for (int32 i = 0; i < data.Length(); i++) objects[i] = (MObject*)MUtils::ToString(data.Get()[i]); MCore::GC::WriteArrayRef(result, Span(objects, data.Length())); Allocator::Free(objects); } void ToNativeArray(Span& result, const MArray* data) { MString** dataPtr = MCore::Array::GetAddress(data); for (int32 i = 0; i < result.Length(); i++) MUtils::ToString(dataPtr[i], result.Get()[i]); } void FreeManaged(MObject* data) { MCore::String::Free((MString*)data); } void FreeManagedArray(MArray* array) { MString** dataPtr = MCore::Array::GetAddress(array); auto length = MCore::Array::GetLength(array); for (int32 i = 0; i < length; i++) MCore::String::Free(dataPtr[i]); MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // Converter for StringView. template<> struct MConverter { MObject* Box(const StringView& data, const MClass* klass) { PLATFORM_DEBUG_BREAK; // FIXME return (MObject*)MUtils::ToString(data); } void Unbox(StringView& result, MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME result = MUtils::ToString((MString*)data); } void ToManaged(StringView& result, const StringView& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(StringView& result, const StringView& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToManagedArray(MArray* result, const Span& data) { PLATFORM_DEBUG_BREAK; // FIXME if (data.Length() == 0) return; MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*)); for (int32 i = 0; i < data.Length(); i++) objects[i] = (MObject*)MUtils::ToString(data.Get()[i]); MCore::GC::WriteArrayRef(result, Span(objects, data.Length())); Allocator::Free(objects); } void ToNativeArray(Span& result, const MArray* data) { PLATFORM_DEBUG_BREAK; // FIXME MString** dataPtr = MCore::Array::GetAddress(data); for (int32 i = 0; i < result.Length(); i++) MUtils::ToString(dataPtr[i], result.Get()[i]); } void FreeManaged(MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME MCore::String::Free((MString*)data); } void FreeManagedArray(MArray* array) { PLATFORM_DEBUG_BREAK; // FIXME MString** dataPtr = MCore::Array::GetAddress(array); auto length = MCore::Array::GetLength(array); for (int32 i = 0; i < length; i++) MCore::String::Free(dataPtr[i]); MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // Converter for Variant. template<> struct MConverter { MObject* Box(const Variant& data, const MClass* klass) { PLATFORM_DEBUG_BREAK; // FIXME return MUtils::BoxVariant(data); } void Unbox(Variant& result, MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME result = MUtils::UnboxVariant(data); } void ToManaged(Variant& result, const Variant& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(Variant& result, const Variant& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToManagedArray(MArray* result, const Span& data) { PLATFORM_DEBUG_BREAK; // FIXME if (data.Length() == 0) return; MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*)); for (int32 i = 0; i < data.Length(); i++) objects[i] = MUtils::BoxVariant(data[i]); MCore::GC::WriteArrayRef(result, Span(objects, data.Length())); Allocator::Free(objects); } void ToNativeArray(Span& result, const MArray* data) { PLATFORM_DEBUG_BREAK; // FIXME MObject** dataPtr = MCore::Array::GetAddress(data); for (int32 i = 0; i < result.Length(); i++) result.Get()[i] = MUtils::UnboxVariant(dataPtr[i]); } void FreeManaged(MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME } void FreeManagedArray(MArray* array) { PLATFORM_DEBUG_BREAK; // FIXME MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // Converter for Scripting Objects (collection of pointers). template struct MConverter::Value>::Type> { MObject* Box(T* data, const MClass* klass) { PLATFORM_DEBUG_BREAK; // FIXME return data ? data->GetOrCreateManagedInstance() : nullptr; } void Unbox(T*& result, MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME result = (T*)ScriptingObject::ToNative(data); } void ToManaged(MObject*& result, const T* data) { //PLATFORM_DEBUG_BREAK; // FIXME result = data ? data->GetOrCreateManagedInstance() : nullptr; } void ToNative(T*& result, const MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME result = (T*)ScriptingObject::ToNative(data); } void ToManagedArray(MArray* result, const Span& data) { if (data.Length() == 0) return; MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*)); for (int32 i = 0; i < data.Length(); i++) objects[i] = data.Get()[i] ? data.Get()[i]->GetOrCreateManagedInstance() : nullptr; MCore::GC::WriteArrayRef(result, Span(objects, data.Length())); Allocator::Free(objects); } void ToNativeArray(Span& result, const MArray* data) { MObject** dataPtr = MCore::Array::GetAddress(data); for (int32 i = 0; i < result.Length(); i++) result.Get()[i] = (T*)ScriptingObject::ToNative(dataPtr[i]); } void FreeManaged(MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME } void FreeManagedArray(MArray* array) { MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // Converter for Scripting Objects (collection of values). template struct MConverter::Value>::Type> { MObject* Box(const T& data, const MClass* klass) { PLATFORM_DEBUG_BREAK; // FIXME return data.GetOrCreateManagedInstance(); } void ToManaged(MObject*& result, const T& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(T& result, const MObject*& data) { PLATFORM_DEBUG_BREAK; // FIXME } /*void ToManaged(MObject*& result, const T*& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(T*& result, const MObject*& data) { PLATFORM_DEBUG_BREAK; // FIXME }*/ void ToManagedArray(MArray* result, const Span& data) { //PLATFORM_DEBUG_BREAK; // FIXME if (data.Length() == 0) return; MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*)); for (int32 i = 0; i < data.Length(); i++) objects[i] = data.Get()[i].GetOrCreateManagedInstance(); MCore::GC::WriteArrayRef(result, Span(objects, data.Length())); Allocator::Free(objects); } void FreeManaged(MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME } void FreeManagedArray(MArray* array) { PLATFORM_DEBUG_BREAK; // FIXME MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // Converter for ScriptingObject References. template class ScriptingObjectReference; template struct MConverter> { MObject* Box(const ScriptingObjectReference& data, const MClass* klass) { PLATFORM_DEBUG_BREAK; // FIXME return data.GetManagedInstance(); } void Unbox(ScriptingObjectReference& result, MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME result = (T*)ScriptingObject::ToNative(data); } void ToManaged(MObject*& result, const ScriptingObjectReference& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(ScriptingObjectReference& result, const MObject*& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToManagedArray(MArray* result, const Span>& data) { PLATFORM_DEBUG_BREAK; // FIXME if (data.Length() == 0) return; MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*)); for (int32 i = 0; i < data.Length(); i++) objects[i] = data[i].GetManagedInstance(); MCore::GC::WriteArrayRef(result, Span(objects, data.Length())); Allocator::Free(objects); } void ToNativeArray(Span>& result, const MArray* data) { PLATFORM_DEBUG_BREAK; // FIXME MObject** dataPtr = MCore::Array::GetAddress(data); for (int32 i = 0; i < result.Length(); i++) result.Get()[i] = (T*)ScriptingObject::ToNative(dataPtr[i]); } void FreeManaged(MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME } void FreeManagedArray(MArray* array) { PLATFORM_DEBUG_BREAK; // FIXME MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // Converter for Asset References. template class AssetReference; template struct MConverter> { MObject* Box(const AssetReference& data, const MClass* klass) { PLATFORM_DEBUG_BREAK; // FIXME return data.GetManagedInstance(); } void Unbox(AssetReference& result, MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME result = (T*)ScriptingObject::ToNative(data); } void ToManaged(MObject*& result, const AssetReference& data) { PLATFORM_DEBUG_BREAK; // FIXME result = data.GetManagedInstance(); } void ToNative(AssetReference& result, const MObject* data) { result = (T*)ScriptingObject::ToNative(data); } void ToManagedArray(MArray* result, const Span>& data) { if (data.Length() == 0) return; MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*)); for (int32 i = 0; i < data.Length(); i++) objects[i] = data[i].GetManagedInstance(); MCore::GC::WriteArrayRef(result, Span(objects, data.Length())); Allocator::Free(objects); } void ToNativeArray(Span>& result, const MArray* data) { //PLATFORM_DEBUG_BREAK; // FIXME MObject** dataPtr = MCore::Array::GetAddress(data); for (int32 i = 0; i < result.Length(); i++) result.Get()[i] = (T*)ScriptingObject::ToNative(dataPtr[i]); } void FreeManaged(MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME } void FreeManagedArray(MArray* array) { MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // TODO: use MarshalAs=Guid on SoftAssetReference to pass guid over bindings and not load asset in glue code template class SoftAssetReference; template struct MConverter> { template void ToManaged(U& result, const SoftAssetReference& data) { PLATFORM_DEBUG_BREAK; // FIXME } template void ToNative(SoftAssetReference& result, const U& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToManaged(MObject*& result, const SoftAssetReference& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(SoftAssetReference& result, const MObject*& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToManagedArray(MArray* result, const Span>& data) { //PLATFORM_DEBUG_BREAK; // FIXME if (data.Length() == 0) return; MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*)); for (int32 i = 0; i < data.Length(); i++) objects[i] = data[i].GetManagedInstance(); MCore::GC::WriteArrayRef(result, Span(objects, data.Length())); Allocator::Free(objects); } void ToNativeArray(Span>& result, const MArray* data) { //PLATFORM_DEBUG_BREAK; // FIXME MObject** dataPtr = MCore::Array::GetAddress(data); for (int32 i = 0; i < result.Length(); i++) result.Get()[i] = (T*)ScriptingObject::ToNative(dataPtr[i]); } void FreeManaged(MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME } void FreeManagedArray(MArray* array) { PLATFORM_DEBUG_BREAK; // FIXME MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; // Converter for Array. template struct MConverter> { void ToManaged(Array& result, const Array& data) { PLATFORM_DEBUG_BREAK; // FIXME } void ToNative(Array& result, const Array& data) { PLATFORM_DEBUG_BREAK; // FIXME } MObject* Box(const Array& data, const MClass* klass) { PLATFORM_DEBUG_BREAK; // FIXME if (!klass) return nullptr; MArray* result = MCore::Array::New(klass->GetElementClass(), data.Count()); MConverter converter; converter.ToManagedArray(result, Span(data.Get(), data.Count())); return (MObject*)result; } void Unbox(Array& result, MObject* data) { MArray* array = MCore::Array::Unbox(data); const int32 length = array ? MCore::Array::GetLength(array) : 0; result.Resize(length); MConverter converter; Span resultSpan(result.Get(), length); converter.ToNativeArray(resultSpan, array); } void FreeManaged(MObject* data) { PLATFORM_DEBUG_BREAK; // FIXME MArray* array = (MArray*)data; MConverter converter; converter.FreeManagedArray(array); //MCore::Array::Free(array); //MCore::GCHandle::Free(*(MGCHandle*)&data); } void FreeManagedArray(MArray* array) { PLATFORM_DEBUG_BREAK; // FIXME MCore::Array::Free(array); MCore::GCHandle::Free(*(MGCHandle*)&array); } }; namespace MUtils { // Outputs the full typename for the type of the specified object. extern FLAXENGINE_API StringAnsiView GetClassFullname(MObject* obj); // Returns the class of the provided object. extern FLAXENGINE_API MClass* GetClass(MObject* object); // Returns the class of the provided type. extern FLAXENGINE_API MClass* GetClass(MTypeObject* type); // Returns the class of the provided VariantType value. extern FLAXENGINE_API MClass* GetClass(const VariantType& value); // Returns the class of the provided Variant value. extern FLAXENGINE_API MClass* GetClass(const Variant& value); // Returns the type of the provided object. extern FLAXENGINE_API MTypeObject* GetType(MObject* object); // Returns the type of the provided class. extern FLAXENGINE_API MTypeObject* GetType(MClass* klass); /// /// Boxes the native value into the managed object. /// /// The value. /// The value type class. template MObject* Box(const T& value, const MClass* valueClass) { MConverter converter; return converter.Box(value, valueClass); } /// /// Unboxes MObject to the native value of the given type. /// /// template T Unbox(MObject* object) { MConverter converter; T result; converter.Unbox(result, object); return result; } /// /// Unboxes MObject to the native value of the given type. /// /// The object. /// True if boxed managed handle should be released. template T Unbox(MObject* object, bool releaseHandle) { MConverter converter; T result; converter.Unbox(result, object); if (releaseHandle) converter.FreeManaged(object); return result; } /// /// Unboxes MObject to the native value of the given type. /// /// template<> inline bool Unbox(MObject* object) { MConverter converter; int32 result; converter.Unbox(*(bool*)&result, object); return result != 0; } /// /// Unboxes MObject to the native value of the given type. /// /// The object. /// True if boxed managed handle should be released. template<> inline bool Unbox(MObject* object, bool releaseHandle) { MConverter converter; int32 result; converter.Unbox(*(bool*)&result, object); if (releaseHandle) converter.FreeManaged(object); return result != 0; } /// /// Releases the managed resources of a boxed object. /// template void FreeManaged(MObject* object) { MConverter converter; converter.FreeManaged(object); } /// /// Releases the managed resources of a boxed object. /// template void FreeManagedArray(MArray* array) { MConverter converter; converter.FreeManagedArray(array); } /// /// Links managed array data to the unmanaged BytesContainer. /// /// The array object. /// The result data container with linked array data bytes (not copied). extern FLAXENGINE_API BytesContainer LinkArray(MArray* arrayObj); /// /// Allocates new managed array of data and copies contents from given native array. /// /// The array object. /// The array values type class. /// The output array. template MArray* ToArray(const Span& data, const MClass* valueClass) { if (!valueClass) return nullptr; MArray* result = MCore::Array::New(valueClass, data.Length()); MConverter converter; converter.ToManagedArray(result, data); return result; } /// /// Allocates new managed array of data and copies contents from given native array. /// /// The array object. /// The array values type class. /// The output array. template FORCE_INLINE MArray* ToArray(const Array& data, const MClass* valueClass) { return MUtils::ToArray(Span(data.Get(), data.Count()), valueClass); } /// /// Converts the managed array into native array container object. /// /// The managed array object. /// The output array. template Array ToArray(MArray* arrayObj) { Array result; const int32 length = arrayObj ? MCore::Array::GetLength(arrayObj) : 0; result.Resize(length); MConverter converter; Span resultSpan(result.Get(), length); converter.ToNativeArray(resultSpan, arrayObj); return result; } /// /// Converts the managed array into native Span. /// /// The managed array object. /// The output array pointer and size. template Span ToSpan(MArray* arrayObj) { T* ptr = (T*)MCore::Array::GetAddress(arrayObj); const int32 length = arrayObj ? MCore::Array::GetLength(arrayObj) : 0; return Span(ptr, length); } /// /// Converts the native array into native Span. /// /// The native array object. /// The output array pointer and size. template FORCE_INLINE Span ToSpan(const Array& data) { return Span(data.Get(), data.Count()); } /// /// Links managed array data to the unmanaged DataContainer (must use simple type like struct or float/int/bool). /// /// The array object. /// The result data (linked not copied). template void ToArray(MArray* arrayObj, DataContainer& result) { const int32 length = arrayObj ? MCore::Array::GetLength(arrayObj) : 0; if (length == 0) { result.Release(); return; } T* bytesRaw = (T*)MCore::Array::GetAddress(arrayObj); result.Link(bytesRaw, length); } /// /// Allocates new managed bytes array and copies data from the given unmanaged data container. /// /// The input data. /// The output array. FORCE_INLINE MArray* ToArray(const Span& data) { return ToArray(data, MCore::TypeCache::Byte); } /// /// Allocates new managed bytes array and copies data from the given unmanaged data container. /// /// The input data. /// The output array. FORCE_INLINE MArray* ToArray(Array& data) { return ToArray(Span(data.Get(), data.Count()), MCore::TypeCache::Byte); } /// /// Allocates new managed strings array and copies data from the given unmanaged data container. /// /// The input data. /// The output array. FORCE_INLINE MArray* ToArray(const Span& data) { return ToArray(data, MCore::TypeCache::String); } /// /// Allocates new managed strings array and copies data from the given unmanaged data container. /// /// The input data. /// The output array. FORCE_INLINE MArray* ToArray(const Array& data) { return ToArray(Span(data.Get(), data.Count()), MCore::TypeCache::String); } #if USE_NETCORE /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE T* ToNativeArray(const Array& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer T* arr = (T*)MCore::GC::AllocateMemory(data.Count() * sizeof(T), true); Platform::MemoryCopy(arr, data.Get(), data.Count() * sizeof(T)); return arr; } /// /// Allocates new managed array of data and copies contents from given native array. /// /// The array object. /// The array values type class. /// The output array. /*template NativeArray ToManagedArrayWrapper(const Span& data, const MClass* valueClass) { if (!valueClass) return nullptr; MArray* result = MCore::Array::New(valueClass, data.Length()); MConverter converter; converter.ToManagedArray(result, data); return result; // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Count(); arr.data = (U*)MCore::GC::AllocateMemory(arr.length * sizeof(U), true); Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(U)); return arr; }*/ /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. /*template FORCE_INLINE NativeArray ToNativeArrayWrapper(const Array& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Count(); arr.data = (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true); Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(T)); return arr; } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE NativeArray ToNativeArrayWrapper(const Array& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Count(); arr.data = (U*)MCore::GC::AllocateMemory(arr.length * sizeof(U), true); // Convert to managed MConverter converter; for (int i = 0; i < arr.length; ++i) arr.data[i] = converter.ToManaged(data[i]); return arr; }*/ /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE NativeArray ToManagedArrayWrapperConvert(const Span& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Length(); arr.data = arr.length > 0 ? (U*)MCore::GC::AllocateMemory(arr.length * sizeof(U), true) : nullptr; // Convert to managed MConverter converter; for (int i = 0; i < arr.length; ++i) converter.ToManaged(arr.data[i], data[i]); return arr; } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE NativeArray ToNativeArrayWrapperConvertGeneric(const Span& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Length(); arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr; // Convert to managed MConverter converter; for (int i = 0; i < arr.length; ++i) { converter.ToNative(arr.data[i], data[i]); } return arr; } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE void ToNativeArrayWrapperConvertGeneric(const Span& data, Array& array) { if (!array.IsEmpty()) PLATFORM_DEBUG_BREAK; // TODO: does the array require ClearDelete instead? auto length = data.Length(); array.Resize(length, false); //array.Clear(); //array.EnsureCapacity(length); MConverter converter; for (int i = 0; i < length; ++i) { // Make sure the destination is default initialized first //array.AddUninitialized(); //array.AddDefault(); //T& dest = array.Get()[i]; //new(&dest)AssetReference(); // Convert from managed converter.ToNative(array.Get()[i], data[i]); } } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE NativeArray ToNativeArrayWrapperConvert(const Span& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Length(); arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr; // Convert to managed MConverter converter; for (int i = 0; i < arr.length; ++i) converter.ToNative(arr.data[i], data[i]); return arr; } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE NativeArray ToNativeArrayWrapperCopy(const Span& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Length(); arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr; Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(T)); return arr; } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. /*FORCE_INLINE NativeArray ToManagedArrayWrapper(const Span& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Length(); arr.data = (Char*)MCore::GC::AllocateMemory(arr.length * sizeof(Char), true); Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(Char)); return arr; }*/ /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE NativeArray ToManagedArrayWrapperConvert(const Span& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Length(); arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr; //Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(T)); // Convert to managed MConverter converter; for (int i = 0; i < arr.length; ++i) converter.ToManaged(arr.data[i], data[i]); return arr; } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE NativeArray ToManagedArrayWrapperCopy(const Span& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Length(); arr.data = arr.length > 0 ? (T*)MCore::GC::AllocateMemory(arr.length * sizeof(T), true) : nullptr; Platform::MemoryCopy(arr.data, data.Get(), arr.length * sizeof(T)); return arr; } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. /*template FORCE_INLINE NativeArray ToManagedArrayWrapperPointer(const Span& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Length(); arr.data = (MObject**)MCore::GC::AllocateMemory(arr.length * sizeof(MObject*), true); // Convert to managed MConverter converter; for (int i = 0; i < arr.length; ++i) { MObject*& ptr = arr.data[i]; const T& asd = data[i]; converter.ToManaged(ptr, asd); } return arr; }*/ /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE NativeArray ToManagedArrayWrapperPointer(const Span& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer NativeArray arr; arr.length = data.Length(); arr.data = arr.length > 0 ? (MObject**)MCore::GC::AllocateMemory(arr.length * sizeof(MObject*), true) : nullptr; // Convert to managed MConverter converter; for (int i = 0; i < arr.length; ++i) converter.ToManaged(arr.data[i], data[i]); return arr; } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. FORCE_INLINE bool* ToBoolArray(const Array& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer bool* arr = (bool*)MCore::GC::AllocateMemory(data.Count() * sizeof(bool), true); memcpy(arr, data.Get(), data.Count() * sizeof(bool)); return arr; } /// /// Allocates new boolean array and copies data from the given unmanaged data container. The managed runtime is responsible for releasing the returned array data. /// /// The input data. /// The output array. template FORCE_INLINE bool* ToBoolArray(const BitArray& data) { // System.Runtime.InteropServices.Marshalling.ArrayMarshaller uses CoTask memory alloc to native data pointer bool* arr = (bool*)MCore::GC::AllocateMemory(data.Count() * sizeof(bool), true); for (int i = 0; i < data.Count(); i++) arr[i] = data[i]; return arr; } #else FORCE_INLINE bool* ToBoolArray(const Array& data) { return nullptr; } template FORCE_INLINE bool* ToBoolArray(const BitArray& data) { return nullptr; } #endif extern void* VariantToManagedArgPtr(Variant& value, MType* type, bool& failed); extern MObject* ToManaged(const Version& value); extern Version ToNative(MObject* value); }; #endif