From 3a6b7ea80b5617062144021167dde07a3d18b3fb Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 3 Jun 2021 15:19:00 +0200 Subject: [PATCH] Add support for `Function<>` as method parameter in scripting --- .../Bindings/BindingsGenerator.Api.cs | 8 +++--- .../Bindings/BindingsGenerator.CSharp.cs | 27 +++++++++++++++++++ .../Bindings/BindingsGenerator.Cpp.cs | 22 +++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Api.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Api.cs index ded954e5a..42f785e16 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Api.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Api.cs @@ -210,17 +210,15 @@ namespace Flax.Build.Bindings if ((typeInfo.Type == "Array" || typeInfo.Type == "Span" || typeInfo.Type == "Dictionary" || typeInfo.Type == "HashSet") && typeInfo.GenericArgs != null) return false; - // Skip for BytesContainer + // Skip for special types if (typeInfo.Type == "BytesContainer" && typeInfo.GenericArgs == null) return false; - - // Skip for Variant if (typeInfo.Type == "Variant" && typeInfo.GenericArgs == null) return false; - - // Skip for VariantType if (typeInfo.Type == "VariantType" && typeInfo.GenericArgs == null) return false; + if (typeInfo.Type == "Function" && typeInfo.GenericArgs != null) + return false; // Find API type info var apiType = FindApiTypeInfo(buildData, typeInfo, caller); diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs index 6d92c3969..41b4eb796 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs @@ -197,6 +197,26 @@ namespace Flax.Build.Bindings if (typeInfo.Type == "BytesContainer" && typeInfo.GenericArgs == null) return "byte[]"; + // Function + if (typeInfo.Type == "Function" && typeInfo.GenericArgs != null) + { + if (typeInfo.GenericArgs.Count == 0) + throw new Exception("Missing function return type."); + if (typeInfo.GenericArgs.Count > 1) + { + var args = string.Empty; + args += GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[1], caller); + for (int i = 2; i < typeInfo.GenericArgs.Count; i++) + args += ", " + GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[i], caller); + if (typeInfo.GenericArgs[0].Type == "void") + return string.Format("Action<{0}>", args); + return string.Format("Func<{0}, {1}>", args, GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller)); + } + if (typeInfo.GenericArgs[0].Type == "void") + return "Action"; + return string.Format("Func<{0}>", GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller)); + } + // Find API type info var apiType = FindApiTypeInfo(buildData, typeInfo, caller); if (apiType != null) @@ -235,6 +255,10 @@ namespace Flax.Build.Bindings if ((typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null) return "IntPtr"; + // Function + if (typeInfo.Type == "Function" && typeInfo.GenericArgs != null) + return "IntPtr"; + return GenerateCSharpNativeToManaged(buildData, typeInfo, caller); } @@ -265,6 +289,9 @@ namespace Flax.Build.Bindings case "ManagedScriptingObject": // object return "FlaxEngine.Object.GetUnmanagedPtr"; + case "Function": + // delegate + return "Marshal.GetFunctionPointerForDelegate"; default: var apiType = FindApiTypeInfo(buildData, typeInfo, caller); if (apiType != null) diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs index a2fffddd4..70627d97e 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs @@ -420,6 +420,13 @@ namespace Flax.Build.Bindings return "ManagedBitArray::ToManaged({0})"; } + // Function + if (typeInfo.Type == "Function" && typeInfo.GenericArgs != null) + { + // TODO: automatic converting managed-native for Function + throw new NotImplementedException("TODO: converting native Function to managed"); + } + var apiType = FindApiTypeInfo(buildData, typeInfo, caller); if (apiType != null) { @@ -606,6 +613,21 @@ namespace Flax.Build.Bindings return "MUtils::LinkArray({0})"; } + // Function + if (typeInfo.Type == "Function" && typeInfo.GenericArgs != null) + { + var args = string.Empty; + if (typeInfo.GenericArgs.Count > 1) + { + args += typeInfo.GenericArgs[1].GetFullNameNative(buildData, caller); + for (int i = 2; i < typeInfo.GenericArgs.Count; i++) + args += ", " + typeInfo.GenericArgs[i].GetFullNameNative(buildData, caller); + } + var T = $"Function<{typeInfo.GenericArgs[0].GetFullNameNative(buildData, caller)}({args})>"; + type = T + "::Signature"; + return T + "({0})"; + } + if (apiType != null) { // Scripting Object (for non-pod types converting only, other API converts managed to unmanaged object in C# wrapper code)