Merge remote-tracking branch 'origin/master' into 1.8
# Conflicts: # Source/Editor/Utilities/EditorUtilities.cpp # Source/Editor/Utilities/EditorUtilities.h
This commit is contained in:
@@ -90,6 +90,15 @@ namespace Flax.Build.Bindings
|
||||
"Int4",
|
||||
};
|
||||
|
||||
private static bool GenerateCSharpUseFixedBuffer(string managedType)
|
||||
{
|
||||
return managedType == "byte" || managedType == "char" ||
|
||||
managedType == "short" || managedType == "ushort" ||
|
||||
managedType == "int" || managedType == "uint" ||
|
||||
managedType == "long" || managedType == "ulong" ||
|
||||
managedType == "float" || managedType == "double";
|
||||
}
|
||||
|
||||
private static string GenerateCSharpDefaultValueNativeToManaged(BuildData buildData, string value, ApiTypeInfo caller, TypeInfo valueType = null, bool attribute = false, string managedType = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
@@ -261,7 +270,7 @@ namespace Flax.Build.Bindings
|
||||
return value;
|
||||
}
|
||||
|
||||
private static string GenerateCSharpNativeToManaged(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller)
|
||||
private static string GenerateCSharpNativeToManaged(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, bool marshalling = false)
|
||||
{
|
||||
string result;
|
||||
if (typeInfo?.Type == null)
|
||||
@@ -271,7 +280,7 @@ namespace Flax.Build.Bindings
|
||||
if (typeInfo.IsArray)
|
||||
{
|
||||
typeInfo.IsArray = false;
|
||||
result = GenerateCSharpNativeToManaged(buildData, typeInfo, caller);
|
||||
result = GenerateCSharpNativeToManaged(buildData, typeInfo, caller, marshalling);
|
||||
typeInfo.IsArray = true;
|
||||
return result + "[]";
|
||||
}
|
||||
@@ -298,7 +307,7 @@ namespace Flax.Build.Bindings
|
||||
|
||||
// Object reference property
|
||||
if (typeInfo.IsObjectRef)
|
||||
return GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller);
|
||||
return GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller, marshalling);
|
||||
if (typeInfo.Type == "SoftTypeReference" || typeInfo.Type == "SoftObjectReference")
|
||||
return typeInfo.Type;
|
||||
|
||||
@@ -308,15 +317,25 @@ namespace Flax.Build.Bindings
|
||||
#else
|
||||
if ((typeInfo.Type == "Array" || typeInfo.Type == "Span" || typeInfo.Type == "DataContainer") && typeInfo.GenericArgs != null)
|
||||
#endif
|
||||
return GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller) + "[]";
|
||||
{
|
||||
var arrayTypeInfo = typeInfo.GenericArgs[0];
|
||||
if (marshalling)
|
||||
{
|
||||
// Convert array that uses different type for marshalling
|
||||
var arrayApiType = FindApiTypeInfo(buildData, arrayTypeInfo, caller);
|
||||
if (arrayApiType != null && arrayApiType.MarshalAs != null)
|
||||
arrayTypeInfo = arrayApiType.MarshalAs;
|
||||
}
|
||||
return GenerateCSharpNativeToManaged(buildData, arrayTypeInfo, caller) + "[]";
|
||||
}
|
||||
|
||||
// Dictionary
|
||||
if (typeInfo.Type == "Dictionary" && typeInfo.GenericArgs != null)
|
||||
return string.Format("System.Collections.Generic.Dictionary<{0}, {1}>", GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller), GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[1], caller));
|
||||
return string.Format("System.Collections.Generic.Dictionary<{0}, {1}>", GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller, marshalling), GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[1], caller, marshalling));
|
||||
|
||||
// HashSet
|
||||
if (typeInfo.Type == "HashSet" && typeInfo.GenericArgs != null)
|
||||
return string.Format("System.Collections.Generic.HashSet<{0}>", GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller));
|
||||
return string.Format("System.Collections.Generic.HashSet<{0}>", GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller, marshalling));
|
||||
|
||||
// BitArray
|
||||
if (typeInfo.Type == "BitArray" && typeInfo.GenericArgs != null)
|
||||
@@ -339,16 +358,16 @@ namespace Flax.Build.Bindings
|
||||
// TODO: generate delegates globally in the module namespace to share more code (smaller binary size)
|
||||
var key = string.Empty;
|
||||
for (int i = 0; i < typeInfo.GenericArgs.Count; i++)
|
||||
key += GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[i], caller);
|
||||
key += GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[i], caller, marshalling);
|
||||
if (!CSharpAdditionalCodeCache.TryGetValue(key, out var delegateName))
|
||||
{
|
||||
delegateName = "Delegate" + CSharpAdditionalCodeCache.Count;
|
||||
var signature = $"public delegate {GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller)} {delegateName}(";
|
||||
var signature = $"public delegate {GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller, marshalling)} {delegateName}(";
|
||||
for (int i = 1; i < typeInfo.GenericArgs.Count; i++)
|
||||
{
|
||||
if (i != 1)
|
||||
signature += ", ";
|
||||
signature += GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[i], caller);
|
||||
signature += GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[i], caller, marshalling);
|
||||
signature += $" arg{(i - 1)}";
|
||||
}
|
||||
signature += ");";
|
||||
@@ -381,11 +400,14 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
typeName += '<';
|
||||
foreach (var arg in typeInfo.GenericArgs)
|
||||
typeName += GenerateCSharpNativeToManaged(buildData, arg, caller);
|
||||
typeName += GenerateCSharpNativeToManaged(buildData, arg, caller, marshalling);
|
||||
typeName += '>';
|
||||
}
|
||||
if (apiType != null)
|
||||
{
|
||||
if (marshalling && apiType.MarshalAs != null)
|
||||
return GenerateCSharpNativeToManaged(buildData, apiType.MarshalAs, caller);
|
||||
|
||||
// Add reference to the namespace
|
||||
CSharpUsedNamespaces.Add(apiType.Namespace);
|
||||
var apiTypeParent = apiType.Parent;
|
||||
@@ -410,11 +432,11 @@ namespace Flax.Build.Bindings
|
||||
return typeName;
|
||||
}
|
||||
|
||||
private static string GenerateCSharpManagedToNativeType(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller)
|
||||
private static string GenerateCSharpManagedToNativeType(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, bool marshalling = false)
|
||||
{
|
||||
// Fixed-size array
|
||||
if (typeInfo.IsArray)
|
||||
return GenerateCSharpNativeToManaged(buildData, typeInfo, caller);
|
||||
return GenerateCSharpNativeToManaged(buildData, typeInfo, caller, marshalling);
|
||||
|
||||
// Find API type info
|
||||
var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
|
||||
@@ -430,7 +452,7 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
|
||||
if (apiType.MarshalAs != null)
|
||||
return GenerateCSharpManagedToNativeType(buildData, new TypeInfo(apiType.MarshalAs), caller);
|
||||
return GenerateCSharpManagedToNativeType(buildData, apiType.MarshalAs, caller, marshalling);
|
||||
if (apiType.IsScriptingObject || apiType.IsInterface)
|
||||
return "IntPtr";
|
||||
}
|
||||
@@ -443,7 +465,7 @@ namespace Flax.Build.Bindings
|
||||
if (typeInfo.Type == "Function" && typeInfo.GenericArgs != null)
|
||||
return "IntPtr";
|
||||
|
||||
return GenerateCSharpNativeToManaged(buildData, typeInfo, caller);
|
||||
return GenerateCSharpNativeToManaged(buildData, typeInfo, caller, marshalling);
|
||||
}
|
||||
|
||||
private static string GenerateCSharpManagedToNativeConverter(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller)
|
||||
@@ -476,6 +498,18 @@ namespace Flax.Build.Bindings
|
||||
case "Function":
|
||||
// delegate
|
||||
return "NativeInterop.GetFunctionPointerForDelegate({0})";
|
||||
case "Array":
|
||||
case "Span":
|
||||
case "DataContainer":
|
||||
if (typeInfo.GenericArgs != null)
|
||||
{
|
||||
// Convert array that uses different type for marshalling
|
||||
var arrayTypeInfo = typeInfo.GenericArgs[0];
|
||||
var arrayApiType = FindApiTypeInfo(buildData, arrayTypeInfo, caller);
|
||||
if (arrayApiType != null && arrayApiType.MarshalAs != null)
|
||||
return $"{{0}}.ConvertArray(x => ({GenerateCSharpNativeToManaged(buildData, arrayApiType.MarshalAs, caller)})x)";
|
||||
}
|
||||
return string.Empty;
|
||||
default:
|
||||
var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
|
||||
if (apiType != null)
|
||||
@@ -522,9 +556,9 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
var apiType = FindApiTypeInfo(buildData, functionInfo.ReturnType, caller);
|
||||
if (apiType != null && apiType.MarshalAs != null)
|
||||
returnValueType = GenerateCSharpNativeToManaged(buildData, new TypeInfo(apiType.MarshalAs), caller);
|
||||
returnValueType = GenerateCSharpNativeToManaged(buildData, apiType.MarshalAs, caller, true);
|
||||
else
|
||||
returnValueType = GenerateCSharpNativeToManaged(buildData, functionInfo.ReturnType, caller);
|
||||
returnValueType = GenerateCSharpNativeToManaged(buildData, functionInfo.ReturnType, caller, true);
|
||||
}
|
||||
|
||||
#if USE_NETCORE
|
||||
@@ -585,7 +619,7 @@ namespace Flax.Build.Bindings
|
||||
contents.Append(", ");
|
||||
separator = true;
|
||||
|
||||
var nativeType = GenerateCSharpManagedToNativeType(buildData, parameterInfo.Type, caller);
|
||||
var nativeType = GenerateCSharpManagedToNativeType(buildData, parameterInfo.Type, caller, true);
|
||||
#if USE_NETCORE
|
||||
string parameterMarshalType = "";
|
||||
if (nativeType == "System.Type")
|
||||
@@ -638,7 +672,7 @@ namespace Flax.Build.Bindings
|
||||
contents.Append(", ");
|
||||
separator = true;
|
||||
|
||||
var nativeType = GenerateCSharpManagedToNativeType(buildData, parameterInfo.Type, caller);
|
||||
var nativeType = GenerateCSharpManagedToNativeType(buildData, parameterInfo.Type, caller, true);
|
||||
#if USE_NETCORE
|
||||
string parameterMarshalType = "";
|
||||
if (parameterInfo.IsOut && parameterInfo.DefaultValue == "var __resultAsRef")
|
||||
@@ -751,7 +785,16 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
}
|
||||
|
||||
contents.Append(");");
|
||||
contents.Append(')');
|
||||
if ((functionInfo.ReturnType.Type == "Array" || functionInfo.ReturnType.Type == "Span" || functionInfo.ReturnType.Type == "DataContainer") && functionInfo.ReturnType.GenericArgs != null)
|
||||
{
|
||||
// Convert array that uses different type for marshalling
|
||||
var arrayTypeInfo = functionInfo.ReturnType.GenericArgs[0];
|
||||
var arrayApiType = FindApiTypeInfo(buildData, arrayTypeInfo, caller);
|
||||
if (arrayApiType != null && arrayApiType.MarshalAs != null)
|
||||
contents.Append($".ConvertArray(x => ({GenerateCSharpNativeToManaged(buildData, arrayTypeInfo, caller)})x)");
|
||||
}
|
||||
contents.Append(';');
|
||||
|
||||
// Return result
|
||||
if (functionInfo.Glue.UseReferenceForResult)
|
||||
@@ -1439,10 +1482,10 @@ namespace Flax.Build.Bindings
|
||||
|
||||
indent += " ";
|
||||
|
||||
StringBuilder toManagedContent = new StringBuilder();
|
||||
StringBuilder toNativeContent = new StringBuilder();
|
||||
StringBuilder freeContents = new StringBuilder();
|
||||
StringBuilder freeContents2 = new StringBuilder();
|
||||
var toManagedContent = GetStringBuilder();
|
||||
var toNativeContent = GetStringBuilder();
|
||||
var freeContents = GetStringBuilder();
|
||||
var freeContents2 = GetStringBuilder();
|
||||
|
||||
{
|
||||
// Native struct begin
|
||||
@@ -1457,10 +1500,9 @@ namespace Flax.Build.Bindings
|
||||
contents.Append(indent + "{");
|
||||
indent += " ";
|
||||
|
||||
toNativeContent.Append($"return new {structureInfo.Name}Internal() {{ ");
|
||||
toManagedContent.Append($"return new {structureInfo.Name}() {{ ");
|
||||
toNativeContent.Append($"var unmanaged = new {structureInfo.Name}Internal();").AppendLine();
|
||||
toManagedContent.Append($"var managed = new {structureInfo.Name}();").AppendLine();
|
||||
|
||||
bool useSeparator = false;
|
||||
contents.AppendLine();
|
||||
foreach (var fieldInfo in structureInfo.Fields)
|
||||
{
|
||||
@@ -1478,11 +1520,7 @@ namespace Flax.Build.Bindings
|
||||
else
|
||||
originalType = type = GenerateCSharpNativeToManaged(buildData, fieldInfo.Type, structureInfo);
|
||||
|
||||
contents.Append(indent).Append(GenerateCSharpAccessLevel(fieldInfo.Access));
|
||||
if (fieldInfo.IsConstexpr)
|
||||
contents.Append("const ");
|
||||
else if (fieldInfo.IsStatic)
|
||||
contents.Append("static ");
|
||||
contents.Append(indent).Append("public ");
|
||||
|
||||
var apiType = FindApiTypeInfo(buildData, fieldInfo.Type, structureInfo);
|
||||
bool internalType = apiType is StructureInfo fieldStructureInfo && UseCustomMarshalling(buildData, fieldStructureInfo, structureInfo);
|
||||
@@ -1490,16 +1528,43 @@ namespace Flax.Build.Bindings
|
||||
|
||||
if (fieldInfo.Type.IsArray && (fieldInfo.NoArray || structureInfo.IsPod))
|
||||
{
|
||||
contents.Append(type).Append(' ').Append(fieldInfo.Name + "0;").AppendLine();
|
||||
for (int i = 1; i < fieldInfo.Type.ArraySize; i++)
|
||||
#if USE_NETCORE
|
||||
if (GenerateCSharpUseFixedBuffer(originalType))
|
||||
{
|
||||
contents.AppendLine();
|
||||
GenerateCSharpAttributes(buildData, contents, indent, structureInfo, fieldInfo, fieldInfo.IsStatic);
|
||||
contents.Append(indent).Append(GenerateCSharpAccessLevel(fieldInfo.Access));
|
||||
if (fieldInfo.IsStatic)
|
||||
contents.Append("static ");
|
||||
contents.Append(type).Append(' ').Append(fieldInfo.Name + i).Append(';').AppendLine();
|
||||
// Use fixed statement with primitive types of buffers
|
||||
contents.Append($"fixed {originalType} {fieldInfo.Name}0[{fieldInfo.Type.ArraySize}];").AppendLine();
|
||||
|
||||
// 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);");
|
||||
toNativeContent.AppendLine($"FlaxEngine.Utils.MemoryCopy(new IntPtr(unmanaged.{fieldInfo.Name}0), new IntPtr(managed.{fieldInfo.Name}0), sizeof({originalType}) * {fieldInfo.Type.ArraySize}ul);");
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Padding in structs for fixed-size array
|
||||
contents.Append(type).Append(' ').Append(fieldInfo.Name).Append("0;").AppendLine();
|
||||
for (int i = 1; i < fieldInfo.Type.ArraySize; i++)
|
||||
{
|
||||
GenerateCSharpAttributes(buildData, contents, indent, structureInfo, fieldInfo, fieldInfo.IsStatic);
|
||||
contents.Append(indent).Append("public ");
|
||||
contents.Append(type).Append(' ').Append(fieldInfo.Name + i).Append(';').AppendLine();
|
||||
}
|
||||
|
||||
// Copy fixed-size array item one-by-one
|
||||
if (fieldInfo.Access == AccessLevel.Public || fieldInfo.Access == AccessLevel.Internal)
|
||||
{
|
||||
for (int i = 0; i < fieldInfo.Type.ArraySize; i++)
|
||||
{
|
||||
toManagedContent.AppendLine($"managed.{fieldInfo.Name}{i} = unmanaged.{fieldInfo.Name}{i};");
|
||||
toNativeContent.AppendLine($"unmanaged.{fieldInfo.Name}{i} = managed.{fieldInfo.Name}{i};");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("TODO: generate utility method to copy private/protected array data items");
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1529,34 +1594,17 @@ namespace Flax.Build.Bindings
|
||||
//else if (type == "Guid")
|
||||
// type = "GuidNative";
|
||||
|
||||
contents.Append(type).Append(' ').Append(fieldInfo.Name);
|
||||
contents.Append(';').AppendLine();
|
||||
contents.Append(type).Append(' ').Append(fieldInfo.Name).Append(';').AppendLine();
|
||||
}
|
||||
|
||||
// Generate struct constructor/getter and deconstructor/setter function
|
||||
if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
|
||||
continue;
|
||||
|
||||
if (useSeparator)
|
||||
{
|
||||
toManagedContent.Append(", ");
|
||||
toNativeContent.Append(", ");
|
||||
freeContents2.Append("");
|
||||
freeContents.Append("");
|
||||
}
|
||||
useSeparator = true;
|
||||
|
||||
toManagedContent.Append(fieldInfo.Name);
|
||||
toManagedContent.Append(" = ");
|
||||
|
||||
toNativeContent.Append(fieldInfo.Name);
|
||||
toNativeContent.Append(" = ");
|
||||
|
||||
toManagedContent.Append("managed.").Append(fieldInfo.Name).Append(" = ");
|
||||
toNativeContent.Append("unmanaged.").Append(fieldInfo.Name).Append(" = ");
|
||||
if (fieldInfo.Type.IsObjectRef)
|
||||
{
|
||||
var managedType = GenerateCSharpNativeToManaged(buildData, fieldInfo.Type.GenericArgs[0], structureInfo);
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{managedType}>(ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target) : null");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name} != null ? ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak) : IntPtr.Zero");
|
||||
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;");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}");
|
||||
|
||||
// Permanent ScriptingObject handle is passed from native side, do not release it
|
||||
@@ -1564,8 +1612,8 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
else if (fieldInfo.Type.Type == "ScriptingObject")
|
||||
{
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<FlaxEngine.Object>(ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target) : null");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name} != null ? ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak) : IntPtr.Zero");
|
||||
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;");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}");
|
||||
|
||||
// Permanent ScriptingObject handle is passed from native side, do not release it
|
||||
@@ -1573,8 +1621,8 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
else if (fieldInfo.Type.IsPtr && originalType != "IntPtr" && !originalType.EndsWith("*"))
|
||||
{
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{originalType}>(ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target) : null");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name} != null ? ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak) : IntPtr.Zero");
|
||||
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;");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Free(); }}");
|
||||
|
||||
// Permanent ScriptingObject handle is passed from native side, do not release it
|
||||
@@ -1582,8 +1630,8 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
else if (fieldInfo.Type.Type == "Dictionary")
|
||||
{
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{originalType}>(ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target) : null");
|
||||
toNativeContent.Append($"ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak)");
|
||||
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);");
|
||||
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(); }}");
|
||||
}
|
||||
@@ -1595,16 +1643,16 @@ namespace Flax.Build.Bindings
|
||||
// Marshal blittable array elements back to original non-blittable elements
|
||||
string originalElementTypeMarshaller = originalElementType + "Marshaller";
|
||||
string internalElementType = $"{originalElementTypeMarshaller}.{originalElementType}Internal";
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.ConvertArray((Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target)).ToSpan<{internalElementType}>(), {originalElementTypeMarshaller}.ToManaged) : null");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name}?.Length > 0 ? ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(NativeInterop.ConvertArray(managed.{fieldInfo.Name}, {originalElementTypeMarshaller}.ToNative)), GCHandleType.Weak) : IntPtr.Zero");
|
||||
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.ConvertArray((Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target)).ToSpan<{internalElementType}>(), {originalElementTypeMarshaller}.ToManaged) : null;");
|
||||
toNativeContent.AppendLine($"managed.{fieldInfo.Name}?.Length > 0 ? ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(NativeInterop.ConvertArray(managed.{fieldInfo.Name}, {originalElementTypeMarshaller}.ToNative)), GCHandleType.Weak) : IntPtr.Zero;");
|
||||
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}.Free(value); }} (Unsafe.As<ManagedArray>(handle.Target)).Free(); handle.Free(); }}");
|
||||
}
|
||||
else if (fieldInfo.Type.GenericArgs[0].IsObjectRef)
|
||||
{
|
||||
// Array elements passed as GCHandles
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.GCHandleArrayToManagedArray<{originalElementType}>(Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target)) : null");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name}?.Length > 0 ? ManagedHandle.ToIntPtr(NativeInterop.ManagedArrayToGCHandleWrappedArray(managed.{fieldInfo.Name}), GCHandleType.Weak) : IntPtr.Zero");
|
||||
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? NativeInterop.GCHandleArrayToManagedArray<{originalElementType}>(Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target)) : null;");
|
||||
toNativeContent.AppendLine($"managed.{fieldInfo.Name}?.Length > 0 ? ManagedHandle.ToIntPtr(NativeInterop.ManagedArrayToGCHandleWrappedArray(managed.{fieldInfo.Name}), GCHandleType.Weak) : IntPtr.Zero;");
|
||||
freeContents.AppendLine($"if (unmanaged.{fieldInfo.Name} != IntPtr.Zero) {{ ManagedHandle handle = ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}); Span<IntPtr> ptrs = (Unsafe.As<ManagedArray>(handle.Target)).ToSpan<IntPtr>(); foreach (var ptr in ptrs) {{ if (ptr != IntPtr.Zero) {{ ManagedHandle.FromIntPtr(ptr).Free(); }} }} (Unsafe.As<ManagedArray>(handle.Target)).Free(); handle.Free(); }}");
|
||||
|
||||
// Permanent ScriptingObject handle is passed from native side, do not release it
|
||||
@@ -1613,53 +1661,53 @@ namespace Flax.Build.Bindings
|
||||
else
|
||||
{
|
||||
// Blittable array elements
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? (Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target)).ToArray<{originalElementType}>() : null");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name}?.Length > 0 ? ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(managed.{fieldInfo.Name}), GCHandleType.Weak) : IntPtr.Zero");
|
||||
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != IntPtr.Zero ? (Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(unmanaged.{fieldInfo.Name}).Target)).ToArray<{originalElementType}>() : null;");
|
||||
toNativeContent.AppendLine($"managed.{fieldInfo.Name}?.Length > 0 ? ManagedHandle.ToIntPtr(ManagedArray.WrapNewArray(managed.{fieldInfo.Name}), GCHandleType.Weak) : IntPtr.Zero;");
|
||||
freeContents.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")
|
||||
{
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != IntPtr.Zero ? Unsafe.As<{originalType}>(ManagedHandle.FromIntPtr(managed.{fieldInfo.Name}).Target) : null");
|
||||
toNativeContent.Append($"ManagedHandle.ToIntPtr(managed.{fieldInfo.Name}, GCHandleType.Weak)");
|
||||
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);");
|
||||
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(); }}");
|
||||
}
|
||||
else if (originalType == "string")
|
||||
{
|
||||
toManagedContent.Append($"ManagedString.ToManaged(managed.{fieldInfo.Name})");
|
||||
toNativeContent.Append($"ManagedString.ToNative(managed.{fieldInfo.Name})");
|
||||
toManagedContent.AppendLine($"ManagedString.ToManaged(unmanaged.{fieldInfo.Name});");
|
||||
toNativeContent.AppendLine($"ManagedString.ToNative(managed.{fieldInfo.Name});");
|
||||
freeContents.AppendLine($"ManagedString.Free(unmanaged.{fieldInfo.Name});");
|
||||
freeContents2.AppendLine($"ManagedString.Free(unmanaged.{fieldInfo.Name});");
|
||||
}
|
||||
else if (originalType == "bool")
|
||||
{
|
||||
toManagedContent.Append($"managed.{fieldInfo.Name} != 0");
|
||||
toNativeContent.Append($"managed.{fieldInfo.Name} ? (byte)1 : (byte)0");
|
||||
toManagedContent.AppendLine($"unmanaged.{fieldInfo.Name} != 0;");
|
||||
toNativeContent.AppendLine($"managed.{fieldInfo.Name} ? (byte)1 : (byte)0;");
|
||||
}
|
||||
else if (fieldInfo.Type.Type == "Variant")
|
||||
{
|
||||
// Variant passed as boxed object handle
|
||||
toManagedContent.Append($"ManagedHandleMarshaller.NativeToManaged.ConvertToManaged(managed.{fieldInfo.Name})");
|
||||
toNativeContent.Append($"ManagedHandleMarshaller.NativeToManaged.ConvertToUnmanaged(managed.{fieldInfo.Name})");
|
||||
toManagedContent.AppendLine($"ManagedHandleMarshaller.NativeToManaged.ConvertToManaged(unmanaged.{fieldInfo.Name});");
|
||||
toNativeContent.AppendLine($"ManagedHandleMarshaller.NativeToManaged.ConvertToUnmanaged(managed.{fieldInfo.Name});");
|
||||
}
|
||||
else if (internalType)
|
||||
{
|
||||
toManagedContent.Append($"{internalTypeMarshaller}.ToManaged(managed.{fieldInfo.Name})");
|
||||
toNativeContent.Append($"{internalTypeMarshaller}.ToNative(managed.{fieldInfo.Name})");
|
||||
toManagedContent.AppendLine($"{internalTypeMarshaller}.ToManaged(unmanaged.{fieldInfo.Name});");
|
||||
toNativeContent.AppendLine($"{internalTypeMarshaller}.ToNative(managed.{fieldInfo.Name});");
|
||||
freeContents.AppendLine($"{internalTypeMarshaller}.Free(unmanaged.{fieldInfo.Name});");
|
||||
freeContents2.AppendLine($"{internalTypeMarshaller}.Free(unmanaged.{fieldInfo.Name});");
|
||||
}
|
||||
/*else if (originalType == "Guid")
|
||||
{
|
||||
toManagedContent.Append("(Guid)managed.").Append(fieldInfo.Name);
|
||||
toManagedContent.Append("(Guid)unmanaged.").Append(fieldInfo.Name);
|
||||
toNativeContent.Append("(GuidNative)managed.").Append(fieldInfo.Name);
|
||||
}*/
|
||||
else
|
||||
{
|
||||
toManagedContent.Append("managed.").Append(fieldInfo.Name);
|
||||
toNativeContent.Append("managed.").Append(fieldInfo.Name);
|
||||
toManagedContent.Append("unmanaged.").Append(fieldInfo.Name).AppendLine(";");
|
||||
toNativeContent.Append("managed.").Append(fieldInfo.Name).AppendLine(";");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1667,8 +1715,8 @@ namespace Flax.Build.Bindings
|
||||
indent = indent.Substring(0, indent.Length - 4);
|
||||
contents.AppendLine(indent + "}").AppendLine();
|
||||
|
||||
toManagedContent.AppendLine(" };");
|
||||
toNativeContent.AppendLine(" };");
|
||||
toNativeContent.Append("return unmanaged;");
|
||||
toManagedContent.Append("return managed;");
|
||||
}
|
||||
|
||||
var indent2 = indent + " ";
|
||||
@@ -1716,7 +1764,7 @@ namespace Flax.Build.Bindings
|
||||
contents.Append(indent).AppendLine("{").Append(indent2).AppendLine(freeContents.Replace("\n", "\n" + indent2).ToString().TrimEnd()).Append(indent).AppendLine("}");
|
||||
|
||||
// Managed/native converters
|
||||
contents.Append(indent).AppendLine($"internal static {structureInfo.Name} ToManaged({structureInfo.Name}Internal managed)");
|
||||
contents.Append(indent).AppendLine($"internal static {structureInfo.Name} ToManaged({structureInfo.Name}Internal unmanaged)");
|
||||
contents.Append(indent).AppendLine("{").Append(indent2).AppendLine(toManagedContent.Replace("\n", "\n" + indent2).ToString().TrimEnd()).Append(indent).AppendLine("}");
|
||||
contents.Append(indent).AppendLine($"internal static {structureInfo.Name}Internal ToNative({structureInfo.Name} managed)");
|
||||
contents.Append(indent).AppendLine("{").Append(indent2).AppendLine(toNativeContent.Replace("\n", "\n" + indent2).ToString().TrimEnd()).Append(indent).AppendLine("}");
|
||||
@@ -1724,6 +1772,11 @@ namespace Flax.Build.Bindings
|
||||
contents.AppendLine("#pragma warning restore 1591");
|
||||
indent = indent.Substring(0, indent.Length - 4);
|
||||
contents.Append(indent).AppendLine("}").AppendLine();
|
||||
|
||||
PutStringBuilder(toManagedContent);
|
||||
PutStringBuilder(toNativeContent);
|
||||
PutStringBuilder(freeContents);
|
||||
PutStringBuilder(freeContents2);
|
||||
}
|
||||
#endif
|
||||
// Struct docs
|
||||
@@ -1771,15 +1824,12 @@ namespace Flax.Build.Bindings
|
||||
managedType = GenerateCSharpNativeToManaged(buildData, fieldInfo.Type, structureInfo);
|
||||
fieldInfo.Type.IsArray = true;
|
||||
#if USE_NETCORE
|
||||
// Use fixed statement with primitive types of buffers
|
||||
if (managedType == "char")
|
||||
if (GenerateCSharpUseFixedBuffer(managedType))
|
||||
{
|
||||
// char's are not blittable, store as short instead
|
||||
contents.Append($"fixed short {fieldInfo.Name}0[{fieldInfo.Type.ArraySize}]; // {managedType}*").AppendLine();
|
||||
}
|
||||
else if (managedType == "byte")
|
||||
{
|
||||
contents.Append($"fixed byte {fieldInfo.Name}0[{fieldInfo.Type.ArraySize}]; // {managedType}*").AppendLine();
|
||||
// Use fixed statement with primitive types of buffers
|
||||
if (managedType == "char")
|
||||
managedType = "short"; // char's are not blittable, store as short instead
|
||||
contents.Append($"fixed {managedType} {fieldInfo.Name}0[{fieldInfo.Type.ArraySize}];").AppendLine();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -1789,7 +1839,6 @@ namespace Flax.Build.Bindings
|
||||
for (int i = 1; i < fieldInfo.Type.ArraySize; i++)
|
||||
{
|
||||
contents.AppendLine();
|
||||
GenerateCSharpComment(contents, indent, fieldInfo.Comment);
|
||||
GenerateCSharpAttributes(buildData, contents, indent, structureInfo, fieldInfo, fieldInfo.IsStatic);
|
||||
contents.Append(indent).Append(GenerateCSharpAccessLevel(fieldInfo.Access));
|
||||
if (fieldInfo.IsStatic)
|
||||
|
||||
Reference in New Issue
Block a user