Various fixes to scripting
This commit is contained in:
@@ -783,7 +783,6 @@ namespace FlaxEngine
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[CustomMarshaller(typeof(Dictionary<,>), MarshalMode.ManagedToUnmanagedIn, typeof(DictionaryMarshaller<,>.ManagedToNative))]
|
||||
@@ -2517,7 +2516,12 @@ namespace FlaxEngine
|
||||
{
|
||||
object fieldOwner = fieldOwnerHandle.Target;
|
||||
FieldHolder field = Unsafe.As<FieldHolder>(fieldHandle.Target);
|
||||
field.field.SetValue(fieldOwner, Marshal.PtrToStructure(valuePtr, field.field.FieldType));
|
||||
object value = null;
|
||||
if (field.field.FieldType.IsValueType)
|
||||
value = Marshal.PtrToStructure(valuePtr, field.field.FieldType);
|
||||
else if (valuePtr != IntPtr.Zero)
|
||||
value = ManagedHandle.FromIntPtr(valuePtr).Target;
|
||||
field.field.SetValue(fieldOwner, value);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#define FLAX_CORECLR_STRING StringAnsi
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// .NET Runtime hosting library that uses Hostfxr (https://github.com/dotnet/runtime).
|
||||
/// </summary>
|
||||
class CoreCLR
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -852,18 +852,21 @@ MONO_API MONO_RT_EXTERNAL_ONLY MonoObject* mono_property_get_value(MonoProperty*
|
||||
|
||||
MONO_API void mono_gc_wbarrier_set_field(MonoObject* obj, void* field_ptr, MonoObject* value)
|
||||
{
|
||||
ASSERT(false);
|
||||
CRASH; // Not supported on CoreCRL
|
||||
}
|
||||
|
||||
MONO_API void mono_gc_wbarrier_set_arrayref(MonoArray* arr, void* slot_ptr, MonoObject* value)
|
||||
{
|
||||
static void* SetArrayValueReferencePtr = CoreCLR::GetStaticMethodPointer(TEXT("SetArrayValueReference"));
|
||||
CoreCLR::CallStaticMethod<void, void*, void*, void*>(SetArrayValueReferencePtr, arr, slot_ptr, value);
|
||||
}
|
||||
|
||||
MONO_API void mono_gc_wbarrier_generic_store(void* ptr, MonoObject* value)
|
||||
{
|
||||
// Ignored
|
||||
*((void**)ptr) = value;
|
||||
*(void**)ptr = value;
|
||||
}
|
||||
|
||||
MONO_API void mono_gc_wbarrier_value_copy(void* dest, /*const*/ void* src, int count, MonoClass* klass)
|
||||
{
|
||||
// Ignored
|
||||
|
||||
@@ -85,6 +85,7 @@ extern "C" FLAXENGINE_API void mono_add_internal_call(const char* name, const vo
|
||||
#else
|
||||
|
||||
#define ADD_INTERNAL_CALL(fullName, method)
|
||||
#define DEFINE_INTERNAL_CALL(returnType) static returnType
|
||||
#define INTERNAL_CALL_CHECK(obj)
|
||||
#define INTERNAL_CALL_CHECK_EXP(expression)
|
||||
#define INTERNAL_CALL_CHECK_RETURN(obj, defaultValue)
|
||||
|
||||
@@ -221,12 +221,12 @@ void ScriptingObject::ChangeID(const Guid& newId)
|
||||
_type.GetType().Module->OnObjectIdChanged(this, prevId);
|
||||
}
|
||||
|
||||
void ScriptingObject::SetManagedInstance(MonoObject* instance)
|
||||
void ScriptingObject::SetManagedInstance(MObject* instance)
|
||||
{
|
||||
ASSERT(_gcHandle == 0);
|
||||
#if USE_NETCORE
|
||||
_gcHandle = (MGCHandle)instance;
|
||||
#else
|
||||
#elif !COMPILE_WITHOUT_CSHARP
|
||||
_gcHandle = MUtils::NewGCHandle(instance, false);
|
||||
#endif
|
||||
}
|
||||
@@ -454,12 +454,12 @@ ManagedScriptingObject::ManagedScriptingObject(const SpawnParams& params)
|
||||
{
|
||||
}
|
||||
|
||||
void ManagedScriptingObject::SetManagedInstance(MonoObject* instance)
|
||||
void ManagedScriptingObject::SetManagedInstance(MObject* instance)
|
||||
{
|
||||
ASSERT(_gcHandle == 0);
|
||||
#if USE_NETCORE
|
||||
_gcHandle = (MGCHandle)instance;
|
||||
#else
|
||||
#elif !COMPILE_WITHOUT_CSHARP
|
||||
_gcHandle = MUtils::NewGCHandleWeakref(instance, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ public:
|
||||
virtual void ChangeID(const Guid& newId);
|
||||
|
||||
public:
|
||||
virtual void SetManagedInstance(MonoObject* instance);
|
||||
virtual void SetManagedInstance(MObject* instance);
|
||||
virtual void OnManagedInstanceDeleted();
|
||||
virtual void OnScriptingDispose();
|
||||
|
||||
@@ -246,7 +246,7 @@ public:
|
||||
|
||||
public:
|
||||
// [ScriptingObject]
|
||||
void SetManagedInstance(MonoObject* instance) override;
|
||||
void SetManagedInstance(MObject* instance) override;
|
||||
void OnManagedInstanceDeleted() override;
|
||||
void OnScriptingDispose() override;
|
||||
bool CreateManaged() override;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
package com.flaxengine;
|
||||
|
||||
|
||||
@@ -578,7 +578,7 @@ namespace Flax.Build.Bindings
|
||||
// Managed class
|
||||
if (apiType.IsClass)
|
||||
{
|
||||
// Use wrapper structure that represents the memory layout of the managed data
|
||||
// Use wrapper that box the data into managed object
|
||||
if (!CppUsedNonPodTypes.Contains(apiType))
|
||||
{
|
||||
CppUsedNonPodTypes.Add(apiType);
|
||||
@@ -784,7 +784,7 @@ namespace Flax.Build.Bindings
|
||||
// Managed class
|
||||
if (apiType.IsClass && !apiType.IsScriptingObject)
|
||||
{
|
||||
// Use wrapper structure that represents the memory layout of the managed data
|
||||
// Use wrapper that unboxes the data into managed object
|
||||
if (!CppUsedNonPodTypes.Contains(apiType))
|
||||
{
|
||||
CppUsedNonPodTypes.Add(apiType);
|
||||
@@ -2152,10 +2152,12 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
if (useScripting && useCSharp)
|
||||
{
|
||||
#if !USE_NETCORE
|
||||
foreach (var e in CppInternalCalls)
|
||||
{
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{e.Key}\", &{e.Value});");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
GenerateCppTypeInitRuntime?.Invoke(buildData, classInfo, contents);
|
||||
|
||||
@@ -2306,10 +2308,12 @@ namespace Flax.Build.Bindings
|
||||
|
||||
if (useCSharp)
|
||||
{
|
||||
#if !USE_NETCORE
|
||||
foreach (var e in CppInternalCalls)
|
||||
{
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{e.Key}\", &{e.Value});");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
GenerateCppTypeInitRuntime?.Invoke(buildData, structureInfo, contents);
|
||||
|
||||
@@ -2809,35 +2813,35 @@ namespace Flax.Build.Bindings
|
||||
// Get the full typename with nested parent prefix
|
||||
var fullName = apiType.FullNameNative;
|
||||
|
||||
// Generate managed type memory layout
|
||||
header.Append("struct ").Append(apiType.Name).Append("Managed").AppendLine();
|
||||
header.Append('{').AppendLine();
|
||||
if (classInfo != null)
|
||||
header.AppendLine(" MonoObject obj;");
|
||||
for (var i = 0; i < fields.Count; i++)
|
||||
{
|
||||
var fieldInfo = fields[i];
|
||||
if (fieldInfo.IsStatic)
|
||||
continue;
|
||||
string type;
|
||||
|
||||
if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
|
||||
{
|
||||
// Fixed-size array that needs to be inlined into structure instead of passing it as managed array
|
||||
fieldInfo.Type.IsArray = false;
|
||||
CppParamsWrappersCache[i] = GenerateCppWrapperNativeToManaged(buildData, fieldInfo.Type, apiType, out type, null);
|
||||
fieldInfo.Type.IsArray = true;
|
||||
header.AppendFormat(" {0} {1}[{2}];", type, fieldInfo.Name, fieldInfo.Type.ArraySize).AppendLine();
|
||||
continue;
|
||||
}
|
||||
|
||||
CppParamsWrappersCache[i] = GenerateCppWrapperNativeToManaged(buildData, fieldInfo.Type, apiType, out type, null);
|
||||
header.AppendFormat(" {0} {1};", type, fieldInfo.Name).AppendLine();
|
||||
}
|
||||
header.Append('}').Append(';').AppendLine();
|
||||
|
||||
if (structureInfo != null)
|
||||
{
|
||||
// Generate managed type memory layout
|
||||
header.Append("struct ").Append(apiType.Name).Append("Managed").AppendLine();
|
||||
header.Append('{').AppendLine();
|
||||
if (classInfo != null)
|
||||
header.AppendLine(" MonoObject obj;");
|
||||
for (var i = 0; i < fields.Count; i++)
|
||||
{
|
||||
var fieldInfo = fields[i];
|
||||
if (fieldInfo.IsStatic)
|
||||
continue;
|
||||
string type;
|
||||
|
||||
if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
|
||||
{
|
||||
// Fixed-size array that needs to be inlined into structure instead of passing it as managed array
|
||||
fieldInfo.Type.IsArray = false;
|
||||
CppParamsWrappersCache[i] = GenerateCppWrapperNativeToManaged(buildData, fieldInfo.Type, apiType, out type, null);
|
||||
fieldInfo.Type.IsArray = true;
|
||||
header.AppendFormat(" {0} {1}[{2}];", type, fieldInfo.Name, fieldInfo.Type.ArraySize).AppendLine();
|
||||
continue;
|
||||
}
|
||||
|
||||
CppParamsWrappersCache[i] = GenerateCppWrapperNativeToManaged(buildData, fieldInfo.Type, apiType, out type, null);
|
||||
header.AppendFormat(" {0} {1};", type, fieldInfo.Name).AppendLine();
|
||||
}
|
||||
header.Append('}').Append(';').AppendLine();
|
||||
|
||||
// Generate forward declarations of structure converting functions
|
||||
header.AppendLine();
|
||||
header.AppendLine("namespace {");
|
||||
@@ -2845,7 +2849,7 @@ namespace Flax.Build.Bindings
|
||||
header.AppendFormat("{1} ToNative(const {0}Managed& value);", apiType.Name, fullName).AppendLine();
|
||||
header.AppendLine("}");
|
||||
|
||||
// Generate MConverter
|
||||
// Generate MConverter for a structure
|
||||
header.Append("template<>").AppendLine();
|
||||
header.AppendFormat("struct MConverter<{0}>", fullName).AppendLine();
|
||||
header.Append('{').AppendLine();
|
||||
@@ -2955,38 +2959,29 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
else if (classInfo != null)
|
||||
{
|
||||
// Generate MConverter
|
||||
// Generate MConverter for a class
|
||||
header.Append("template<>").AppendLine();
|
||||
header.AppendFormat("struct MConverter<{0}>", fullName).AppendLine();
|
||||
header.Append('{').AppendLine();
|
||||
|
||||
header.AppendFormat(" static MonoObject* Box(const {0}& data, MonoClass* klass)", fullName).AppendLine();
|
||||
header.Append(" {").AppendLine();
|
||||
header.AppendFormat(" auto obj = ({0}Managed*)mono_object_new(mono_domain_get(), klass);", fullName).AppendLine();
|
||||
header.Append(" MonoObject* obj = mono_object_new(mono_domain_get(), klass);").AppendLine();
|
||||
for (var i = 0; i < fields.Count; i++)
|
||||
{
|
||||
var fieldInfo = fields[i];
|
||||
if (fieldInfo.IsStatic || fieldInfo.IsConstexpr)
|
||||
continue;
|
||||
|
||||
if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
|
||||
{
|
||||
// Fixed-size array needs to unbox every item manually if not using managed array
|
||||
if (fieldInfo.Type.IsPod(buildData, apiType))
|
||||
header.AppendFormat(" Platform::MemoryCopy(obj->{0}, data.{0}, sizeof({2}) * {1});", fieldInfo.Name, fieldInfo.Type.ArraySize, fieldInfo.Type).AppendLine();
|
||||
else
|
||||
header.AppendFormat(" for (int32 i = 0; i < {0}; i++)", fieldInfo.Type.ArraySize).AppendLine().AppendFormat(" obj->{0}[i] = data.{0}[i];", fieldInfo.Name).AppendLine();
|
||||
continue;
|
||||
}
|
||||
|
||||
var wrapper = CppParamsWrappersCache[i];
|
||||
var fieldType = FindApiTypeInfo(buildData, fieldInfo.Type, apiType);
|
||||
if (fieldInfo == null || fieldType.IsValueType) // TODO: support any value type (eg. by boxing)
|
||||
throw new Exception($"Not supported field {fieldInfo.Type} {fieldInfo.Name} in class {classInfo.Name}.");
|
||||
|
||||
var wrapper = GenerateCppWrapperNativeToManaged(buildData, fieldInfo.Type, apiType, out var type, null);
|
||||
var value = string.IsNullOrEmpty(wrapper) ? "data." + fieldInfo.Name : string.Format(wrapper, "data." + fieldInfo.Name);
|
||||
if (fieldInfo.Type.IsPod(buildData, apiType))
|
||||
header.AppendFormat(" obj->{0} = {1};", fieldInfo.Name, value).AppendLine();
|
||||
else
|
||||
header.AppendFormat(" MONO_OBJECT_SETREF(obj, {0}, {1});", fieldInfo.Name, value).AppendLine();
|
||||
header.AppendFormat(" mono_field_set_value(obj, mono_class_get_field_from_name(klass, \"{0}\"), {1});", fieldInfo.Name, value).AppendLine();
|
||||
}
|
||||
header.Append(" return (MonoObject*)obj;").AppendLine();
|
||||
header.Append(" return obj;").AppendLine();
|
||||
header.Append(" }").AppendLine();
|
||||
|
||||
header.AppendFormat(" static MonoObject* Box(const {0}& data)", fullName).AppendLine();
|
||||
@@ -2995,9 +2990,10 @@ namespace Flax.Build.Bindings
|
||||
header.Append(" return Box(data, klass);").AppendLine();
|
||||
header.Append(" }").AppendLine();
|
||||
|
||||
header.AppendFormat(" static void Unbox({0}& result, MonoObject* data)", fullName).AppendLine();
|
||||
header.AppendFormat(" static void Unbox({0}& result, MonoObject* obj)", fullName).AppendLine();
|
||||
header.Append(" {").AppendLine();
|
||||
header.AppendFormat(" auto obj = ({0}Managed*)data;", fullName).AppendLine();
|
||||
header.Append(" MonoClass* klass = mono_object_get_class(obj);").AppendLine();
|
||||
header.Append(" void* v = nullptr;").AppendLine();
|
||||
for (var i = 0; i < fields.Count; i++)
|
||||
{
|
||||
var fieldInfo = fields[i];
|
||||
@@ -3005,33 +3001,12 @@ namespace Flax.Build.Bindings
|
||||
continue;
|
||||
|
||||
CppNonPodTypesConvertingGeneration = true;
|
||||
var wrapper = GenerateCppWrapperManagedToNative(buildData, fieldInfo.Type, apiType, out _, out _, null, out _);
|
||||
var wrapper = GenerateCppWrapperManagedToNative(buildData, fieldInfo.Type, apiType, out var type, out _, null, out _);
|
||||
CppNonPodTypesConvertingGeneration = false;
|
||||
|
||||
if (fieldInfo.Type.IsArray)
|
||||
{
|
||||
// Fixed-size array needs to unbox every item manually
|
||||
if (fieldInfo.NoArray)
|
||||
{
|
||||
if (fieldInfo.Type.IsPod(buildData, apiType))
|
||||
header.AppendFormat(" Platform::MemoryCopy(result.{0}, obj->{0}, sizeof({2}) * {1});", fieldInfo.Name, fieldInfo.Type.ArraySize, fieldInfo.Type).AppendLine();
|
||||
else
|
||||
header.AppendFormat(" for (int32 i = 0; i < {0}; i++)", fieldInfo.Type.ArraySize).AppendLine().AppendFormat(" result.{0}[i] = obj->{0}[i];", fieldInfo.Name).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
wrapper = string.Format(wrapper.Remove(wrapper.Length - 6), string.Format("obj->{0}", fieldInfo.Name));
|
||||
header.AppendFormat(" auto tmp{0} = {1};", fieldInfo.Name, wrapper).AppendLine();
|
||||
header.AppendFormat(" for (int32 i = 0; i < {0} && i < tmp{1}.Count(); i++)", fieldInfo.Type.ArraySize, fieldInfo.Name).AppendLine();
|
||||
header.AppendFormat(" result.{0}[i] = tmp{0}[i];", fieldInfo.Name).AppendLine();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(wrapper))
|
||||
header.AppendFormat(" result.{0} = obj->{0};", fieldInfo.Name).AppendLine();
|
||||
else
|
||||
header.AppendFormat(" result.{0} = {1};", fieldInfo.Name, string.Format(wrapper, string.Format("obj->{0}", fieldInfo.Name))).AppendLine();
|
||||
header.AppendFormat(" mono_field_get_value(obj, mono_class_get_field_from_name(klass, \"{0}\"), &v);", fieldInfo.Name).AppendLine();
|
||||
var value = $"({type})v";
|
||||
header.AppendFormat(" result.{0} = {1};", fieldInfo.Name, string.IsNullOrEmpty(wrapper) ? value : string.Format(wrapper, value)).AppendLine();
|
||||
}
|
||||
header.Append(" }").AppendLine();
|
||||
|
||||
@@ -3052,7 +3027,7 @@ namespace Flax.Build.Bindings
|
||||
header.AppendFormat(" void ToNativeArray(Array<{0}, AllocationType>& result, MonoArray* data, int32 length)", fullName).AppendLine();
|
||||
header.Append(" {").AppendLine();
|
||||
header.Append(" for (int32 i = 0; i < length; i++)").AppendLine();
|
||||
header.AppendFormat(" Unbox(result[i], (MonoObject*)mono_array_addr_with_size(data, sizeof({0}Managed), length));", fullName).AppendLine();
|
||||
header.AppendFormat(" Unbox(result[i], (MonoObject*)mono_array_addr_with_size(data, sizeof(MonoObject*), length));", fullName).AppendLine();
|
||||
header.Append(" }").AppendLine();
|
||||
|
||||
header.Append('}').Append(';').AppendLine();
|
||||
|
||||
Reference in New Issue
Block a user