Add support for passing the object reference as scripting function output result

This commit is contained in:
2021-11-05 11:46:40 +01:00
parent 406102fd25
commit 5bd3032f78
3 changed files with 58 additions and 25 deletions
@@ -362,6 +362,11 @@ namespace Flax.Build.Bindings
contents.Append("out ");
else if (parameterInfo.IsRef || UsePassByReference(buildData, parameterInfo.Type, caller))
contents.Append("ref ");
// Out parameters that need additional converting will be converted at the native side (eg. object reference)
if (parameterInfo.IsOut && !string.IsNullOrEmpty(GenerateCSharpManagedToNativeConverter(buildData, parameterInfo.Type, caller)))
nativeType = parameterInfo.Type.Type;
contents.Append(nativeType);
contents.Append(' ');
contents.Append(parameterInfo.Name);
@@ -399,16 +404,15 @@ namespace Flax.Build.Bindings
{
contents.Append("return ");
}
contents.Append("Internal_").Append(functionInfo.UniqueName).Append('(');
// Pass parameters
var separator = false;
if (!functionInfo.IsStatic)
{
contents.Append("__unmanagedPtr");
separator = true;
}
for (var i = 0; i < functionInfo.Parameters.Count; i++)
{
var parameterInfo = functionInfo.Parameters[i];
@@ -416,29 +420,29 @@ namespace Flax.Build.Bindings
contents.Append(", ");
separator = true;
var convertFunc = GenerateCSharpManagedToNativeConverter(buildData, parameterInfo.Type, caller);
if (string.IsNullOrWhiteSpace(convertFunc))
{
if (parameterInfo.IsOut)
contents.Append("out ");
else if (parameterInfo.IsRef || UsePassByReference(buildData, parameterInfo.Type, caller))
contents.Append("ref ");
if (parameterInfo.IsOut)
contents.Append("out ");
else if (parameterInfo.IsRef || UsePassByReference(buildData, parameterInfo.Type, caller))
contents.Append("ref ");
var convertFunc = CppParamsWrappersCache[i];
var paramName = isSetter ? "value" : parameterInfo.Name;
if (string.IsNullOrWhiteSpace(convertFunc) || parameterInfo.IsOut)
{
// Pass value
contents.Append(isSetter ? "value" : parameterInfo.Name);
contents.Append(paramName);
}
else
{
if (parameterInfo.IsOut)
throw new Exception($"Cannot use Out meta on parameter {parameterInfo} in function {functionInfo.Name} in {caller}.");
if (parameterInfo.IsRef)
throw new Exception($"Cannot use Ref meta on parameter {parameterInfo} in function {functionInfo.Name} in {caller}.");
throw new Exception($"Cannot use Ref meta on parameter {parameterInfo} in function {functionInfo.Name} in {caller}. Use API_PARAM(Out) if you want to pass it as a result reference.");
// Convert value
contents.Append(string.Format(convertFunc, isSetter ? "value" : parameterInfo.Name));
contents.Append(string.Format(convertFunc, paramName));
}
}
// Pass additional parameters
var customParametersCount = functionInfo.Glue.CustomParameters?.Count ?? 0;
for (var i = 0; i < customParametersCount; i++)
{
@@ -448,7 +452,7 @@ namespace Flax.Build.Bindings
separator = true;
var convertFunc = GenerateCSharpManagedToNativeConverter(buildData, parameterInfo.Type, caller);
if (string.IsNullOrWhiteSpace(convertFunc))
if (string.IsNullOrWhiteSpace(convertFunc) || parameterInfo.IsOut)
{
if (parameterInfo.IsOut)
contents.Append("out ");
@@ -466,6 +470,8 @@ namespace Flax.Build.Bindings
}
contents.Append(");");
// Return result
if (functionInfo.Glue.UseReferenceForResult)
{
contents.Append(" return resultAsRef;");
@@ -358,10 +358,8 @@ namespace Flax.Build.Bindings
// Use dynamic array as wrapper container for fixed-size native arrays
if (typeInfo.IsArray)
{
typeInfo.IsArray = false;
var arrayType = new TypeInfo { Type = "Array", GenericArgs = new List<TypeInfo> { typeInfo, }, };
var arrayType = new TypeInfo { Type = "Array", GenericArgs = new List<TypeInfo> { new TypeInfo(typeInfo) { IsArray = false } } };
var result = GenerateCppWrapperNativeToManaged(buildData, arrayType, caller, out type, functionInfo);
typeInfo.IsArray = true;
return result.Replace("{0}", $"Span<{typeInfo.Type}>({{0}}, {typeInfo.ArraySize})");
}
@@ -533,10 +531,8 @@ namespace Flax.Build.Bindings
// Use dynamic array as wrapper container for fixed-size native arrays
if (typeInfo.IsArray)
{
typeInfo.IsArray = false;
var arrayType = new TypeInfo { Type = "Array", GenericArgs = new List<TypeInfo> { typeInfo, }, };
var arrayType = new TypeInfo { Type = "Array", GenericArgs = new List<TypeInfo> { new TypeInfo(typeInfo) { IsArray = false } } };
var result = GenerateCppWrapperManagedToNative(buildData, arrayType, caller, out type, functionInfo, out needLocalVariable);
typeInfo.IsArray = true;
return result + ".Get()";
}
@@ -776,6 +772,12 @@ namespace Flax.Build.Bindings
CppParamsThatNeedConversion[i] = false;
CppParamsWrappersCache[i] = GenerateCppWrapperManagedToNative(buildData, parameterInfo.Type, caller, out var managedType, functionInfo, out CppParamsThatNeedLocalVariable[i]);
// Out parameters that need additional converting will be converted at the native side (eg. object reference)
var isOutWithManagedConverter = parameterInfo.IsOut && !string.IsNullOrEmpty(GenerateCSharpManagedToNativeConverter(buildData, parameterInfo.Type, caller));
if (isOutWithManagedConverter)
managedType = "MonoObject*";
contents.Append(managedType);
if (parameterInfo.IsRef || parameterInfo.IsOut || UsePassByReference(buildData, parameterInfo.Type, caller))
contents.Append('*');
@@ -894,9 +896,11 @@ namespace Flax.Build.Bindings
var apiType = FindApiTypeInfo(buildData, parameterInfo.Type, caller);
if (apiType != null)
{
// TODO: maybe for Out-only params we could skip copying from managed data? see RayCastHit usage converted here from RayCastHitManaged
contents.AppendFormat(" auto {0}Temp = {1};", parameterInfo.Name, param).AppendLine();
if (parameterInfo.Type.IsPtr)
if (parameterInfo.IsOut)
contents.AppendFormat(" {1} {0}Temp;", parameterInfo.Name, new TypeInfo(parameterInfo.Type) { IsRef = false }.GetFullNameNative(buildData, caller)).AppendLine();
else
contents.AppendFormat(" auto {0}Temp = {1};", parameterInfo.Name, param).AppendLine();
if (parameterInfo.Type.IsPtr && !parameterInfo.Type.IsRef)
callParams += "&";
callParams += parameterInfo.Name;
callParams += "Temp";
+24 -1
View File
@@ -11,7 +11,7 @@ namespace Flax.Build.Bindings
/// <summary>
/// The native type information for bindings generator.
/// </summary>
public class TypeInfo : IEquatable<TypeInfo>, IBindingsCache
public class TypeInfo : IEquatable<TypeInfo>, IBindingsCache, ICloneable
{
public string Type;
public bool IsConst;
@@ -33,6 +33,23 @@ namespace Flax.Build.Bindings
/// </summary>
public bool IsConstRef => IsRef && IsConst;
public TypeInfo()
{
}
public TypeInfo(TypeInfo other)
{
Type = other.Type;
IsConst = other.IsConst;
IsRef = other.IsRef;
IsPtr = other.IsPtr;
IsArray = other.IsArray;
IsBitField = other.IsBitField;
ArraySize = other.ArraySize;
BitSize = other.BitSize;
GenericArgs = other.GenericArgs != null ? new List<TypeInfo>(other.GenericArgs) : null;
}
/// <summary>
/// Gets a value indicating whether this type is POD (plain old data).
/// </summary>
@@ -183,5 +200,11 @@ namespace Flax.Build.Bindings
return hashCode;
}
}
/// <inheritdoc />
public object Clone()
{
return new TypeInfo(this);
}
}
}