Fix scripting bindings codegen for SoftTypeReference and SceneReference

#2761
This commit is contained in:
Wojtek Figat
2025-02-26 22:43:30 +01:00
parent 809fd2653a
commit b2c8c4018c
8 changed files with 95 additions and 37 deletions

View File

@@ -74,7 +74,7 @@ namespace FlaxEngine
/// </summary> /// </summary>
/// <param name="knowledge">The knowledge container to access.</param> /// <param name="knowledge">The knowledge container to access.</param>
/// <param name="value">The value to set.</param> /// <param name="value">The value to set.</param>
/// <returns>True if set value value, otherwise false.</returns> /// <returns>True if set value, otherwise false.</returns>
public bool Set(BehaviorKnowledge knowledge, object value) public bool Set(BehaviorKnowledge knowledge, object value)
{ {
return knowledge != null && knowledge.Set(Path, value); return knowledge != null && knowledge.Set(Path, value);

View File

@@ -3151,6 +3151,13 @@ Variant Variant::Parse(const StringView& text, const VariantType& type)
return result; return result;
} }
Variant Variant::Typename(const StringAnsiView& value)
{
Variant result;
result.SetTypename(value);
return result;
}
bool Variant::CanCast(const Variant& v, const VariantType& to) bool Variant::CanCast(const Variant& v, const VariantType& to)
{ {
if (v.Type == to) if (v.Type == to)

View File

@@ -410,6 +410,8 @@ public:
return MoveTemp(v); return MoveTemp(v);
} }
static Variant Typename(const StringAnsiView& value);
static bool CanCast(const Variant& v, const VariantType& to); static bool CanCast(const Variant& v, const VariantType& to);
static Variant Cast(const Variant& v, const VariantType& to); static Variant Cast(const Variant& v, const VariantType& to);
static bool NearEqual(const Variant& a, const Variant& b, float epsilon = 1e-6f); static bool NearEqual(const Variant& a, const Variant& b, float epsilon = 1e-6f);

View File

@@ -38,6 +38,16 @@ namespace FlaxEngine
_typeName = typeName; _typeName = typeName;
} }
/// <summary>
/// Implicit cast operator from type name to string.
/// </summary>
/// <param name="s">The soft type reference.</param>
/// <returns>The type name.</returns>
public static implicit operator string(SoftTypeReference s)
{
return s._typeName;
}
/// <summary> /// <summary>
/// Gets the soft type reference from full name. /// Gets the soft type reference from full name.
/// </summary> /// </summary>

View File

@@ -12,7 +12,7 @@
/// The soft reference to the scripting type contained in the scripting assembly. /// The soft reference to the scripting type contained in the scripting assembly.
/// </summary> /// </summary>
template<typename T = ScriptingObject> template<typename T = ScriptingObject>
API_STRUCT(InBuild) struct SoftTypeReference API_STRUCT(InBuild, MarshalAs=StringAnsi) struct SoftTypeReference
{ {
protected: protected:
StringAnsi _typeName; StringAnsi _typeName;
@@ -64,7 +64,7 @@ public:
return *this; return *this;
} }
FORCE_INLINE SoftTypeReference& operator=(const StringAnsiView& s) FORCE_INLINE SoftTypeReference& operator=(const StringAnsiView& s) noexcept
{ {
_typeName = s; _typeName = s;
return *this; return *this;
@@ -95,6 +95,16 @@ public:
return _typeName.HasChars(); return _typeName.HasChars();
} }
operator StringAnsi() const
{
return _typeName;
}
String ToString() const
{
return _typeName.ToString();
}
public: public:
// Gets the type full name (eg. FlaxEngine.Actor). // Gets the type full name (eg. FlaxEngine.Actor).
StringAnsiView GetTypeName() const StringAnsiView GetTypeName() const

View File

@@ -7,6 +7,8 @@
#include "Engine/Core/Collections/Array.h" #include "Engine/Core/Collections/Array.h"
#include "Engine/Scripting/ScriptingObject.h" #include "Engine/Scripting/ScriptingObject.h"
#include "Engine/Scripting/SerializableScriptingObject.h" #include "Engine/Scripting/SerializableScriptingObject.h"
#include "Engine/Scripting/SoftTypeReference.h"
#include "Engine/Content/SceneReference.h"
// Test default values init on fields. // Test default values init on fields.
API_STRUCT(NoDefault) struct TestDefaultValues API_STRUCT(NoDefault) struct TestDefaultValues
@@ -124,10 +126,17 @@ API_STRUCT(NoDefault) struct TestStruct : public ISerializable
API_FIELD() Float3 Vector = Float3::One; API_FIELD() Float3 Vector = Float3::One;
// Ref // Ref
API_FIELD() ScriptingObject* Object = nullptr; API_FIELD() ScriptingObject* Object = nullptr;
// Soft Type Ref
API_FIELD() SoftTypeReference<ScriptingObject> SoftTypeRef;
// Scene Ref
API_FIELD() SceneReference SceneRef;
friend bool operator==(const TestStruct& lhs, const TestStruct& rhs) friend bool operator==(const TestStruct& lhs, const TestStruct& rhs)
{ {
return lhs.Vector == rhs.Vector && lhs.Object == rhs.Object; return lhs.Vector == rhs.Vector &&
lhs.Object == rhs.Object &&
lhs.SoftTypeRef == rhs.SoftTypeRef &&
lhs.SceneRef == rhs.SceneRef;
} }
}; };

View File

@@ -1605,41 +1605,43 @@ namespace Flax.Build.Bindings
if (fieldInfo.IsStatic || fieldInfo.IsConstexpr) if (fieldInfo.IsStatic || fieldInfo.IsConstexpr)
continue; continue;
var marshalType = fieldInfo.Type;
var apiType = FindApiTypeInfo(buildData, marshalType, structureInfo);
if (apiType != null && apiType.MarshalAs != null)
marshalType = apiType.MarshalAs;
bool internalType = apiType is StructureInfo fieldStructureInfo && UseCustomMarshalling(buildData, fieldStructureInfo, structureInfo);
string type, originalType; string type, originalType;
if (fieldInfo.Type.IsArray && (fieldInfo.NoArray || structureInfo.IsPod)) if (marshalType.IsArray && (fieldInfo.NoArray || structureInfo.IsPod))
{ {
// Fixed-size array that needs to be inlined into structure instead of passing it as managed array // Fixed-size array that needs to be inlined into structure instead of passing it as managed array
fieldInfo.Type.IsArray = false; marshalType.IsArray = false;
originalType = type = GenerateCSharpNativeToManaged(buildData, fieldInfo.Type, structureInfo); originalType = type = GenerateCSharpNativeToManaged(buildData, marshalType, structureInfo);
fieldInfo.Type.IsArray = true; marshalType.IsArray = true;
} }
else else
originalType = type = GenerateCSharpNativeToManaged(buildData, fieldInfo.Type, structureInfo); originalType = type = GenerateCSharpNativeToManaged(buildData, marshalType, structureInfo);
if (apiType != null && apiType.MarshalAs != null)
Log.Error("marshal as into type: " + type);
structContents.Append(structIndent).Append("public "); structContents.Append(structIndent).Append("public ");
var apiType = FindApiTypeInfo(buildData, fieldInfo.Type, structureInfo);
bool internalType = apiType is StructureInfo fieldStructureInfo && UseCustomMarshalling(buildData, fieldStructureInfo, structureInfo);
string internalTypeMarshaller = ""; string internalTypeMarshaller = "";
if (marshalType.IsArray && (fieldInfo.NoArray || structureInfo.IsPod))
if (fieldInfo.Type.IsArray && (fieldInfo.NoArray || structureInfo.IsPod))
{ {
#if USE_NETCORE #if USE_NETCORE
if (GenerateCSharpUseFixedBuffer(originalType)) if (GenerateCSharpUseFixedBuffer(originalType))
{ {
// Use fixed statement with primitive types of buffers // Use fixed statement with primitive types of buffers
structContents.Append($"fixed {originalType} {fieldInfo.Name}0[{fieldInfo.Type.ArraySize}];").AppendLine(); structContents.Append($"fixed {originalType} {fieldInfo.Name}0[{marshalType.ArraySize}];").AppendLine();
// Copy fixed-size array // Copy fixed-size array
toManagedContent.AppendLine($"FlaxEngine.Utils.MemoryCopy(new IntPtr(managed.{fieldInfo.Name}0), new IntPtr(unmanaged.{fieldInfo.Name}0), sizeof({originalType}) * {fieldInfo.Type.ArraySize}ul);"); toManagedContent.AppendLine($"FlaxEngine.Utils.MemoryCopy(new IntPtr(managed.{fieldInfo.Name}0), new IntPtr(unmanaged.{fieldInfo.Name}0), sizeof({originalType}) * {marshalType.ArraySize}ul);");
toNativeContent.AppendLine($"FlaxEngine.Utils.MemoryCopy(new IntPtr(unmanaged.{fieldInfo.Name}0), new IntPtr(managed.{fieldInfo.Name}0), sizeof({originalType}) * {fieldInfo.Type.ArraySize}ul);"); toNativeContent.AppendLine($"FlaxEngine.Utils.MemoryCopy(new IntPtr(unmanaged.{fieldInfo.Name}0), new IntPtr(managed.{fieldInfo.Name}0), sizeof({originalType}) * {marshalType.ArraySize}ul);");
} }
else else
#endif #endif
{ {
// Padding in structs for fixed-size array // Padding in structs for fixed-size array
structContents.Append(type).Append(' ').Append(fieldInfo.Name).Append("0;").AppendLine(); structContents.Append(type).Append(' ').Append(fieldInfo.Name).Append("0;").AppendLine();
for (int i = 1; i < fieldInfo.Type.ArraySize; i++) for (int i = 1; i < marshalType.ArraySize; i++)
{ {
GenerateCSharpAttributes(buildData, structContents, structIndent, structureInfo, fieldInfo, fieldInfo.IsStatic); GenerateCSharpAttributes(buildData, structContents, structIndent, structureInfo, fieldInfo, fieldInfo.IsStatic);
structContents.Append(structIndent).Append("public "); structContents.Append(structIndent).Append("public ");
@@ -1649,7 +1651,7 @@ namespace Flax.Build.Bindings
// Copy fixed-size array item one-by-one // Copy fixed-size array item one-by-one
if (fieldInfo.Access == AccessLevel.Public || fieldInfo.Access == AccessLevel.Internal) if (fieldInfo.Access == AccessLevel.Public || fieldInfo.Access == AccessLevel.Internal)
{ {
for (int i = 0; i < fieldInfo.Type.ArraySize; i++) for (int i = 0; i < marshalType.ArraySize; i++)
{ {
toManagedContent.AppendLine($"managed.{fieldInfo.Name}{i} = unmanaged.{fieldInfo.Name}{i};"); toManagedContent.AppendLine($"managed.{fieldInfo.Name}{i} = unmanaged.{fieldInfo.Name}{i};");
toNativeContent.AppendLine($"unmanaged.{fieldInfo.Name}{i} = managed.{fieldInfo.Name}{i};"); toNativeContent.AppendLine($"unmanaged.{fieldInfo.Name}{i} = managed.{fieldInfo.Name}{i};");
@@ -1664,23 +1666,23 @@ namespace Flax.Build.Bindings
} }
else else
{ {
if (fieldInfo.Type.IsObjectRef || fieldInfo.Type.Type == "Dictionary") if (marshalType.IsObjectRef || marshalType.Type == "Dictionary")
type = "IntPtr"; type = "IntPtr";
else if (fieldInfo.Type.IsPtr && !originalType.EndsWith("*")) else if (marshalType.IsPtr && !originalType.EndsWith("*"))
type = "IntPtr"; type = "IntPtr";
else if (fieldInfo.Type.Type == "Array" || fieldInfo.Type.Type == "Span" || fieldInfo.Type.Type == "DataContainer" || fieldInfo.Type.Type == "BytesContainer") else if (marshalType.Type == "Array" || marshalType.Type == "Span" || marshalType.Type == "DataContainer" || marshalType.Type == "BytesContainer")
{ {
type = "IntPtr"; type = "IntPtr";
apiType = FindApiTypeInfo(buildData, fieldInfo.Type.GenericArgs[0], structureInfo); apiType = FindApiTypeInfo(buildData, marshalType.GenericArgs[0], structureInfo);
internalType = apiType is StructureInfo elementStructureInfo && UseCustomMarshalling(buildData, elementStructureInfo, structureInfo); internalType = apiType is StructureInfo elementStructureInfo && UseCustomMarshalling(buildData, elementStructureInfo, structureInfo);
} }
else if (fieldInfo.Type.Type == "Version") else if (marshalType.Type == "Version")
type = "IntPtr"; type = "IntPtr";
else if (type == "string") else if (type == "string")
type = "IntPtr"; type = "IntPtr";
else if (type == "bool") else if (type == "bool")
type = "byte"; type = "byte";
else if (fieldInfo.Type.Type == "Variant") else if (marshalType.Type == "Variant")
type = "IntPtr"; type = "IntPtr";
else if (internalType) else if (internalType)
{ {
@@ -1695,9 +1697,9 @@ namespace Flax.Build.Bindings
// Generate struct constructor/getter and deconstructor/setter function // Generate struct constructor/getter and deconstructor/setter function
toManagedContent.Append("managed.").Append(fieldInfo.Name).Append(" = "); toManagedContent.Append("managed.").Append(fieldInfo.Name).Append(" = ");
toNativeContent.Append("unmanaged.").Append(fieldInfo.Name).Append(" = "); toNativeContent.Append("unmanaged.").Append(fieldInfo.Name).Append(" = ");
if (fieldInfo.Type.IsObjectRef) if (marshalType.IsObjectRef)
{ {
var managedType = GenerateCSharpNativeToManaged(buildData, fieldInfo.Type.GenericArgs[0], structureInfo); var managedType = GenerateCSharpNativeToManaged(buildData, marshalType.GenericArgs[0], structureInfo);
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{managedType}>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;"); toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{managedType}>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;");
toNativeContent.AppendLine($"managed.{fieldInfo.Name} != null ? ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak) : IntPtr.Zero;"); toNativeContent.AppendLine($"managed.{fieldInfo.Name} != null ? ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak) : IntPtr.Zero;");
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}"); freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}");
@@ -1705,7 +1707,7 @@ namespace Flax.Build.Bindings
// Permanent ScriptingObject handle is passed from native side, do not release it // Permanent ScriptingObject handle is passed from native side, do not release it
//freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}"); //freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}");
} }
else if (fieldInfo.Type.Type == "ScriptingObject") else if (marshalType.Type == "ScriptingObject")
{ {
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<FlaxEngine.Object>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;"); toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<FlaxEngine.Object>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;");
toNativeContent.AppendLine($"managed.{fieldInfo.Name} != null ? ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak) : IntPtr.Zero;"); toNativeContent.AppendLine($"managed.{fieldInfo.Name} != null ? ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak) : IntPtr.Zero;");
@@ -1714,7 +1716,7 @@ namespace Flax.Build.Bindings
// Permanent ScriptingObject handle is passed from native side, do not release it // Permanent ScriptingObject handle is passed from native side, do not release it
//freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}"); //freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}");
} }
else if (fieldInfo.Type.IsPtr && originalType != "IntPtr" && !originalType.EndsWith("*")) else if (marshalType.IsPtr && originalType != "IntPtr" && !originalType.EndsWith("*"))
{ {
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{originalType}>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;"); toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{originalType}>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;");
toNativeContent.AppendLine($"managed.{fieldInfo.Name} != null ? ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak) : IntPtr.Zero;"); toNativeContent.AppendLine($"managed.{fieldInfo.Name} != null ? ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak) : IntPtr.Zero;");
@@ -1723,14 +1725,14 @@ namespace Flax.Build.Bindings
// Permanent ScriptingObject handle is passed from native side, do not release it // Permanent ScriptingObject handle is passed from native side, do not release it
//freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}"); //freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}");
} }
else if (fieldInfo.Type.Type == "Dictionary") else if (marshalType.Type == "Dictionary")
{ {
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{originalType}>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;"); toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{originalType}>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;");
toNativeContent.AppendLine($"ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak);"); toNativeContent.AppendLine($"ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak);");
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}"); freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}");
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}"); freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}");
} }
else if (fieldInfo.Type.Type == "Array" || fieldInfo.Type.Type == "Span" || fieldInfo.Type.Type == "DataContainer" || fieldInfo.Type.Type == "BytesContainer") else if (marshalType.Type == "Array" || marshalType.Type == "Span" || marshalType.Type == "DataContainer" || marshalType.Type == "BytesContainer")
{ {
string originalElementType = originalType.Substring(0, originalType.Length - 2); string originalElementType = originalType.Substring(0, originalType.Length - 2);
if (internalType) if (internalType)
@@ -1744,7 +1746,7 @@ namespace Flax.Build.Bindings
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<{internalElementType}> values = (Unsafe.As<ManagedArray>(handle.Target)).ToSpan<{internalElementType}>(); foreach (var value in values) {{ {originalElementTypeMarshaller}.Free(value); }} (Unsafe.As<ManagedArray>(handle.Target)).Free(); handle.Free(); }}"); freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<{internalElementType}> values = (Unsafe.As<ManagedArray>(handle.Target)).ToSpan<{internalElementType}>(); foreach (var value in values) {{ {originalElementTypeMarshaller}.Free(value); }} (Unsafe.As<ManagedArray>(handle.Target)).Free(); handle.Free(); }}");
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<{internalElementType}> values = (Unsafe.As<ManagedArray>(handle.Target)).ToSpan<{internalElementType}>(); foreach (var value in values) {{ {originalElementTypeMarshaller}.NativeToManaged.Free(value); }} (Unsafe.As<ManagedArray>(handle.Target)).Free(); handle.Free(); }}"); freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<{internalElementType}> values = (Unsafe.As<ManagedArray>(handle.Target)).ToSpan<{internalElementType}>(); foreach (var value in values) {{ {originalElementTypeMarshaller}.NativeToManaged.Free(value); }} (Unsafe.As<ManagedArray>(handle.Target)).Free(); handle.Free(); }}");
} }
else if (fieldInfo.Type.GenericArgs[0].IsObjectRef) else if (marshalType.GenericArgs[0].IsObjectRef)
{ {
// Array elements passed as GCHandles // Array elements passed as GCHandles
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.GCHandleArrayToManagedArray<{originalElementType}>(Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target)) : null;"); toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.GCHandleArrayToManagedArray<{originalElementType}>(Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target)) : null;");
@@ -1763,7 +1765,7 @@ namespace Flax.Build.Bindings
freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); (Unsafe.As<ManagedArray>(handle.Target)).Free(); handle.Free(); }}"); freeContents2.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); (Unsafe.As<ManagedArray>(handle.Target)).Free(); handle.Free(); }}");
} }
} }
else if (fieldInfo.Type.Type == "Version") else if (marshalType.Type == "Version")
{ {
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{originalType}>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;"); toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{originalType}>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target) : null;");
toNativeContent.AppendLine($"ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak);"); toNativeContent.AppendLine($"ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak);");
@@ -1782,7 +1784,7 @@ namespace Flax.Build.Bindings
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != 0;"); toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != 0;");
toNativeContent.AppendLine($"managed.{fieldInfo.Name} ? (byte)1 : (byte)0;"); toNativeContent.AppendLine($"managed.{fieldInfo.Name} ? (byte)1 : (byte)0;");
} }
else if (fieldInfo.Type.Type == "Variant") else if (marshalType.Type == "Variant")
{ {
// Variant passed as boxed object handle // Variant passed as boxed object handle
toManagedContent.AppendLine($"ManagedHandleMarshaller.NativeToManaged.ConvertToManaged(unmanaged.{fieldInfo.Name});"); toManagedContent.AppendLine($"ManagedHandleMarshaller.NativeToManaged.ConvertToManaged(unmanaged.{fieldInfo.Name});");

View File

@@ -169,6 +169,8 @@ namespace Flax.Build.Bindings
return $"Variant(StringAnsiView({value}))"; return $"Variant(StringAnsiView({value}))";
if (typeInfo.IsObjectRef) if (typeInfo.IsObjectRef)
return $"Variant({value}.Get())"; return $"Variant({value}.Get())";
if (typeInfo.Type == "SoftTypeReference")
return $"Variant::Typename(StringAnsiView({value}))";
if (typeInfo.IsArray) if (typeInfo.IsArray)
{ {
var wrapperName = GenerateCppWrapperNativeToVariantMethodName(typeInfo); var wrapperName = GenerateCppWrapperNativeToVariantMethodName(typeInfo);
@@ -227,6 +229,8 @@ namespace Flax.Build.Bindings
return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((ScriptingObject*){value})"; return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((ScriptingObject*){value})";
if (typeInfo.IsObjectRef) if (typeInfo.IsObjectRef)
return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((Asset*){value})"; return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((Asset*){value})";
if (typeInfo.Type == "SoftTypeReference")
return $"(StringAnsiView){value}";
if (typeInfo.IsArray) if (typeInfo.IsArray)
throw new Exception($"Not supported type to convert from the Variant to fixed-size array '{typeInfo}[{typeInfo.ArraySize}]'."); throw new Exception($"Not supported type to convert from the Variant to fixed-size array '{typeInfo}[{typeInfo.ArraySize}]'.");
if (typeInfo.Type == "Array" && typeInfo.GenericArgs != null) if (typeInfo.Type == "Array" && typeInfo.GenericArgs != null)
@@ -258,10 +262,24 @@ namespace Flax.Build.Bindings
if (apiType.IsScriptingObject) if (apiType.IsScriptingObject)
return $"ScriptingObject::Cast<{typeInfo.Type}>((ScriptingObject*){value})"; return $"ScriptingObject::Cast<{typeInfo.Type}>((ScriptingObject*){value})";
if (apiType.IsStruct && !CppInBuildVariantStructures.Contains(apiType.Name)) if (apiType.IsStruct && !CppInBuildVariantStructures.Contains(apiType.Name))
{
var name = apiType.FullNameNative;
if (typeInfo.GenericArgs != null)
{
name += '<';
for (var i = 0; i < typeInfo.GenericArgs.Count; i++)
{
if (i != 0)
name += ", ";
name += typeInfo.GenericArgs[i];
}
name += '>';
}
if (typeInfo.IsPtr) if (typeInfo.IsPtr)
return $"({apiType.FullNameNative}*){value}.AsBlob.Data"; return $"({name}*){value}.AsBlob.Data";
else else
return $"*({apiType.FullNameNative}*){value}.AsBlob.Data"; return $"*({name}*){value}.AsBlob.Data";
}
} }
if (typeInfo.IsPtr) if (typeInfo.IsPtr)