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:
Wojtek Figat
2024-02-19 22:26:16 +01:00
219 changed files with 4189 additions and 2372 deletions

View File

@@ -22,7 +22,7 @@ namespace Flax.Build.Bindings
public string[] Comment;
public bool IsInBuild;
public bool IsDeprecated;
public string MarshalAs;
public TypeInfo MarshalAs;
internal bool IsInited;
internal TypedefInfo Instigator;

View File

@@ -197,7 +197,7 @@ namespace Flax.Build.Bindings
if (apiType != null)
{
if (apiType.MarshalAs != null)
return UsePassByReference(buildData, new TypeInfo(apiType.MarshalAs), caller);
return UsePassByReference(buildData, apiType.MarshalAs, caller);
// Skip for scripting objects
if (apiType.IsScriptingObject)

View File

@@ -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)

View File

@@ -19,7 +19,7 @@ namespace Flax.Build.Bindings
partial class BindingsGenerator
{
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
private const int CacheVersion = 21;
private const int CacheVersion = 22;
internal static void Write(BinaryWriter writer, string e)
{

View File

@@ -167,11 +167,7 @@ namespace Flax.Build.Bindings
return $"Variant(StringView({value}))";
if (typeInfo.Type == "StringAnsi")
return $"Variant(StringAnsiView({value}))";
if (typeInfo.Type == "AssetReference" ||
typeInfo.Type == "WeakAssetReference" ||
typeInfo.Type == "SoftAssetReference" ||
typeInfo.Type == "ScriptingObjectReference" ||
typeInfo.Type == "SoftObjectReference")
if (typeInfo.IsObjectRef)
return $"Variant({value}.Get())";
if (typeInfo.IsArray)
{
@@ -227,10 +223,10 @@ namespace Flax.Build.Bindings
return $"(StringAnsiView){value}";
if (typeInfo.IsPtr && typeInfo.IsConst && typeInfo.Type == "Char")
return $"((StringView){value}).GetText()"; // (StringView)Variant, if not empty, is guaranteed to point to a null-terminated buffer.
if (typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftAssetReference")
return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((Asset*){value})";
if (typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "SoftObjectReference")
return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((ScriptingObject*){value})";
if (typeInfo.IsObjectRef)
return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((Asset*){value})";
if (typeInfo.IsArray)
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)
@@ -309,7 +305,7 @@ namespace Flax.Build.Bindings
private static string GenerateCppGetMClass(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, FunctionInfo functionInfo)
{
// Optimal path for in-build types
var managedType = GenerateCSharpNativeToManaged(buildData, typeInfo, caller);
var managedType = GenerateCSharpNativeToManaged(buildData, typeInfo, caller, true);
switch (managedType)
{
// In-built types (cached by the engine on startup)
@@ -392,7 +388,7 @@ namespace Flax.Build.Bindings
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
// Optimal path for in-build types
var managedType = GenerateCSharpNativeToManaged(buildData, typeInfo, caller);
var managedType = GenerateCSharpNativeToManaged(buildData, typeInfo, caller, true);
switch (managedType)
{
case "bool":
@@ -514,11 +510,7 @@ namespace Flax.Build.Bindings
return "MUtils::ToManaged({0})";
default:
// Object reference property
if ((typeInfo.Type == "ScriptingObjectReference" ||
typeInfo.Type == "AssetReference" ||
typeInfo.Type == "WeakAssetReference" ||
typeInfo.Type == "SoftAssetReference" ||
typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
if (typeInfo.IsObjectRef)
{
type = "MObject*";
return "{0}.GetManagedInstance()";
@@ -527,16 +519,28 @@ namespace Flax.Build.Bindings
// Array or DataContainer
if ((typeInfo.Type == "Array" || typeInfo.Type == "Span" || typeInfo.Type == "DataContainer") && typeInfo.GenericArgs != null)
{
var arrayTypeInfo = typeInfo.GenericArgs[0];
#if USE_NETCORE
// Boolean arrays does not support custom marshalling for some unknown reason
if (typeInfo.GenericArgs[0].Type == "bool")
if (arrayTypeInfo.Type == "bool")
{
type = "bool*";
return "MUtils::ToBoolArray({0})";
}
var arrayApiType = FindApiTypeInfo(buildData, arrayTypeInfo, caller);
#endif
type = "MArray*";
return "MUtils::ToArray({0}, " + GenerateCppGetMClass(buildData, typeInfo.GenericArgs[0], caller, functionInfo) + ")";
if (arrayApiType != null && arrayApiType.MarshalAs != null)
{
// Convert array that uses different type for marshalling
if (arrayApiType != null && arrayApiType.MarshalAs != null)
arrayTypeInfo = arrayApiType.MarshalAs; // Convert array that uses different type for marshalling
var genericArgs = arrayApiType.MarshalAs.GetFullNameNative(buildData, caller);
if (typeInfo.GenericArgs.Count != 1)
genericArgs += ", " + typeInfo.GenericArgs[1];
return "MUtils::ToArray(Array<" + genericArgs + ">({0}), " + GenerateCppGetMClass(buildData, arrayTypeInfo, caller, functionInfo) + ")";
}
return "MUtils::ToArray({0}, " + GenerateCppGetMClass(buildData, arrayTypeInfo, caller, functionInfo) + ")";
}
// Span
@@ -597,7 +601,7 @@ namespace Flax.Build.Bindings
CppReferencesFiles.Add(apiType.File);
if (apiType.MarshalAs != null)
return GenerateCppWrapperNativeToManaged(buildData, new TypeInfo(apiType.MarshalAs), caller, out type, functionInfo);
return GenerateCppWrapperNativeToManaged(buildData, apiType.MarshalAs, caller, out type, functionInfo);
// Scripting Object
if (apiType.IsScriptingObject)
@@ -704,11 +708,7 @@ namespace Flax.Build.Bindings
return "MUtils::ToNative({0})";
default:
// Object reference property
if ((typeInfo.Type == "ScriptingObjectReference" ||
typeInfo.Type == "AssetReference" ||
typeInfo.Type == "WeakAssetReference" ||
typeInfo.Type == "SoftAssetReference" ||
typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
if (typeInfo.IsObjectRef)
{
// For non-pod types converting only, other API converts managed to unmanaged object in C# wrapper code)
if (CppNonPodTypesConvertingGeneration)
@@ -731,11 +731,26 @@ namespace Flax.Build.Bindings
// Array
if (typeInfo.Type == "Array" && typeInfo.GenericArgs != null)
{
var T = typeInfo.GenericArgs[0].GetFullNameNative(buildData, caller);
type = "MArray*";
var arrayTypeInfo = typeInfo.GenericArgs[0];
var arrayApiType = FindApiTypeInfo(buildData, arrayTypeInfo, caller);
if (arrayApiType != null && arrayApiType.MarshalAs != null)
arrayTypeInfo = arrayApiType.MarshalAs;
var genericArgs = arrayTypeInfo.GetFullNameNative(buildData, caller);
if (typeInfo.GenericArgs.Count != 1)
return "MUtils::ToArray<" + T + ", " + typeInfo.GenericArgs[1] + ">({0})";
return "MUtils::ToArray<" + T + ">({0})";
genericArgs += ", " + typeInfo.GenericArgs[1];
type = "MArray*";
var result = "MUtils::ToArray<" + genericArgs + ">({0})";
if (arrayApiType != null && arrayApiType.MarshalAs != null)
{
// Convert array that uses different type for marshalling
genericArgs = typeInfo.GenericArgs[0].GetFullNameNative(buildData, caller);
if (typeInfo.GenericArgs.Count != 1)
genericArgs += ", " + typeInfo.GenericArgs[1];
result = $"Array<{genericArgs}>({result})";
}
return result;
}
// Span or DataContainer
@@ -801,7 +816,7 @@ namespace Flax.Build.Bindings
if (apiType != null)
{
if (apiType.MarshalAs != null)
return GenerateCppWrapperManagedToNative(buildData, new TypeInfo(apiType.MarshalAs), caller, out type, out apiType, functionInfo, out needLocalVariable);
return GenerateCppWrapperManagedToNative(buildData, apiType.MarshalAs, caller, out type, out apiType, functionInfo, out needLocalVariable);
// Scripting Object (for non-pod types converting only, other API converts managed to unmanaged object in C# wrapper code)
if (CppNonPodTypesConvertingGeneration && apiType.IsScriptingObject && typeInfo.IsPtr)

View File

@@ -185,6 +185,11 @@ namespace Flax.Build.Bindings
tag.Value = tag.Value.Substring(1, tag.Value.Length - 2);
if (tag.Value.Contains("\\\""))
tag.Value = tag.Value.Replace("\\\"", "\"");
token = context.Tokenizer.NextToken();
if (token.Type == TokenType.Multiply)
tag.Value += token.Value;
else
context.Tokenizer.PreviousToken();
parameters.Add(tag);
break;
case TokenType.Whitespace:
@@ -647,7 +652,7 @@ namespace Flax.Build.Bindings
desc.Namespace = tag.Value;
break;
case "marshalas":
desc.MarshalAs = tag.Value;
desc.MarshalAs = TypeInfo.FromString(tag.Value);
break;
case "tag":
ParseTag(ref desc.Tags, tag);
@@ -1236,7 +1241,7 @@ namespace Flax.Build.Bindings
desc.Namespace = tag.Value;
break;
case "marshalas":
desc.MarshalAs = tag.Value;
desc.MarshalAs = TypeInfo.FromString(tag.Value);
break;
case "tag":
ParseTag(ref desc.Tags, tag);

View File

@@ -180,6 +180,17 @@ namespace Flax.Build.Bindings
return sb.ToString();
}
public static TypeInfo FromString(string text)
{
var result = new TypeInfo(text);
if (result.Type.EndsWith('*'))
{
result.IsPtr = true;
result.Type = result.Type.Substring(0, result.Type.Length - 1);
}
return result;
}
public string ToString(bool canRef = true)
{
var sb = new StringBuilder(64);

View File

@@ -9,32 +9,30 @@ namespace Flax.Build
/// </summary>
public static class FileCache
{
private static Dictionary<string, FileInfo> fileInfoCache = new Dictionary<string, FileInfo>();
private static readonly Dictionary<string, FileInfo> _cache = new();
public static void FileRemoveFromCache(string path)
{
//fileInfoCache[path].Refresh();
fileInfoCache.Remove(path);
_cache.Remove(path);
}
public static bool Exists(string path)
{
if (fileInfoCache.TryGetValue(path, out var fileInfo))
if (_cache.TryGetValue(path, out var fileInfo))
return fileInfo.Exists;
fileInfo = new FileInfo(path);
fileInfoCache.Add(path, fileInfo);
_cache.Add(path, fileInfo);
return fileInfo.Exists;
}
public static DateTime GetLastWriteTime(string path)
{
if (fileInfoCache.TryGetValue(path, out var fileInfo))
if (_cache.TryGetValue(path, out var fileInfo))
return fileInfo.LastWriteTime;
fileInfo = new FileInfo(path);
fileInfoCache.Add(path, fileInfo);
_cache.Add(path, fileInfo);
return fileInfo.LastWriteTime;
}
}

View File

@@ -845,11 +845,11 @@ namespace Flax.Build
foreach (var moduleName in moduleOptions.PrivateDependencies.Concat(moduleOptions.PublicDependencies))
{
var dependencyModule = buildData.Rules.GetModule(moduleName);
if (dependencyModule != null &&
!string.IsNullOrEmpty(dependencyModule.BinaryModuleName) &&
dependencyModule.BinaryModuleName != binaryModule.Key &&
if (dependencyModule != null &&
!string.IsNullOrEmpty(dependencyModule.BinaryModuleName) &&
dependencyModule.BinaryModuleName != binaryModule.Key &&
!moduleNamesUsed.Contains(dependencyModule.BinaryModuleName) &&
GetModuleProject(dependencyModule, project) != null &&
GetModuleProject(dependencyModule, project) != null &&
buildData.Modules.TryGetValue(dependencyModule, out var dependencyOptions))
{
// Import symbols from referenced binary module

View File

@@ -77,14 +77,10 @@ namespace Flax.Build
var architectureId = RuntimeInformation.ProcessArchitecture;
switch (architectureId)
{
case Architecture.X86:
return TargetArchitecture.x86;
case Architecture.X64:
return TargetArchitecture.x64;
case Architecture.Arm:
return TargetArchitecture.ARM;
case Architecture.Arm64:
return TargetArchitecture.ARM64;
case Architecture.X86: return TargetArchitecture.x86;
case Architecture.X64: return TargetArchitecture.x64;
case Architecture.Arm: return TargetArchitecture.ARM;
case Architecture.Arm64: return TargetArchitecture.ARM64;
default: throw new NotImplementedException(string.Format("Unsupported build platform {0}.", architectureId));
}
}
@@ -290,12 +286,9 @@ namespace Flax.Build
var subdir = "Binaries/Editor/";
switch (Platform.BuildTargetPlatform)
{
case TargetPlatform.Windows:
return subdir + "Win64";
case TargetPlatform.Linux:
return subdir + "Linux";
case TargetPlatform.Mac:
return subdir + "Mac";
case TargetPlatform.Windows: return subdir + "Win64";
case TargetPlatform.Linux: return subdir + "Linux";
case TargetPlatform.Mac: return subdir + "Mac";
}
throw new NotImplementedException();
}

View File

@@ -802,9 +802,12 @@ namespace Flax.Build.Plugins
// Serialize base type
if (type.BaseType != null && type.BaseType.FullName != "System.ValueType" && type.BaseType.FullName != "FlaxEngine.Object" && type.BaseType.CanBeResolved())
{
GenerateSerializeCallback(module, il, type.BaseType.Resolve(), serialize);
GenerateSerializeCallback(module, il, type.BaseType, serialize);
}
if (type.HasGenericParameters) // TODO: implement network replication for generic classes
MonoCecil.CompilationError($"Not supported generic type '{type.FullName}' for network replication.");
var ildContext = new DotnetIlContext(il);
// Serialize all type fields marked with NetworkReplicated attribute
@@ -874,12 +877,13 @@ namespace Flax.Build.Plugins
return m;
}
private static void GenerateSerializeCallback(ModuleDefinition module, ILProcessor il, TypeDefinition type, bool serialize)
private static void GenerateSerializeCallback(ModuleDefinition module, ILProcessor il, TypeReference type, bool serialize)
{
if (type.IsScriptingObject())
{
// NetworkReplicator.InvokeSerializer(typeof(<type>), instance, stream, <serialize>)
il.Emit(OpCodes.Ldtoken, module.ImportReference(type));
module.ImportReference(type);
il.Emit(OpCodes.Ldtoken, type);
module.GetType("System.Type", out var typeType);
var getTypeFromHandle = typeType.Resolve().GetMethod("GetTypeFromHandle");
il.Emit(OpCodes.Call, module.ImportReference(getTypeFromHandle));

View File

@@ -58,7 +58,7 @@ namespace Flax.Deploy
DeployFile(src, dst, buildToolExe);
CodeSign(Path.Combine(dst, buildToolExe));
var buildToolDll = "Flax.Build.dll";
DeployFile(src, dst,buildToolDll);
DeployFile(src, dst, buildToolDll);
CodeSign(Path.Combine(dst, buildToolDll));
DeployFile(src, dst, "Flax.Build.xml", true);
DeployFile(src, dst, "Flax.Build.pdb");

View File

@@ -128,7 +128,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Mac:
{
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
RunCmake(root, platform, architecture, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + globalConfig);
Utilities.Run("make", null, null, root, Utilities.RunOptions.ThrowExceptionOnError);

View File

@@ -49,7 +49,7 @@ namespace Flax.Deps.Dependencies
}
}
}
/// <inheritdoc />
public override void Build(BuildOptions options)
{
@@ -185,16 +185,16 @@ namespace Flax.Deps.Dependencies
// Print the NvCloth version
Log.Info($"Building {File.ReadAllLines(Path.Combine(root, "README.md"))[0].Trim()} to {platform} {architecture}");
// Generate project files
SetupDirectory(buildFolder, false);
Utilities.FileDelete(Path.Combine(cmakeFolder, "CMakeCache.txt"));
cmakeArgs += $" -DPX_STATIC_LIBRARIES=1 -DPX_OUTPUT_DLL_DIR=\"{Path.Combine(buildFolder, "bin")}\" -DPX_OUTPUT_LIB_DIR=\"{Path.Combine(buildFolder, "lib")}\" -DPX_OUTPUT_EXE_DIR=\"{Path.Combine(buildFolder, "bin")}\"";
RunCmake(cmakeFolder, platform, architecture, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + cmakeArgs, envVars);
// Run build
Utilities.Run("cmake", "--build . --config Release", null, cmakeFolder, Utilities.RunOptions.ThrowExceptionOnError, envVars);
// Deploy binaries
var libs = new[]
{

View File

@@ -172,7 +172,7 @@ namespace Flax.Deps.Dependencies
var buildDir = Path.Combine(root, "build");
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
SetupDirectory(buildDir, true);
RunCmake(buildDir, platform, architecture, ".. -DLIBTYPE=STATIC -DCMAKE_BUILD_TYPE=Release " + config);

View File

@@ -95,7 +95,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Linux:
{
// Build for Linux
var settings = new []
var settings = new[]
{
"--without-librtmp",
"--without-ssl",
@@ -126,7 +126,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Mac:
{
// Build for Mac
var settings = new []
var settings = new[]
{
"--with-secure-transport",
"--without-librtmp",
@@ -137,7 +137,7 @@ namespace Flax.Deps.Dependencies
"--enable-static",
"-disable-ldap --disable-sspi --disable-ftp --disable-file --disable-dict --disable-telnet --disable-tftp --disable-rtsp --disable-pop3 --disable-imap --disable-smtp --disable-gopher --disable-smb",
};
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
var arch = GetAppleArchName(architecture);
var archName = arch + "-apple-darwin19";
@@ -146,7 +146,7 @@ namespace Flax.Deps.Dependencies
var compilerFlags = string.Format("-mmacosx-version-min={0} -arch {1}", Configuration.MacOSXMinVer, arch);
var envVars = new Dictionary<string, string>
{
{ "CC", "clang" },
{ "CC", "clang" },
{ "CXX", "clang" },
{ "CFLAGS", compilerFlags },
{ "CXXFLAGS", compilerFlags },

View File

@@ -247,7 +247,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Mac:
{
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
SetupDirectory(buildDir, true);
RunCmake(buildDir, platform, architecture, ".. -DCMAKE_BUILD_TYPE=Release");

View File

@@ -130,7 +130,7 @@ namespace Flax.Deps.Dependencies
};
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
RunCmake(root, platform, architecture, cmakeArgs);
Utilities.Run("cmake", string.Format("--build . --config {0} --target install", configuration), null, buildDir, Utilities.RunOptions.ConsoleLogOutput);

View File

@@ -217,7 +217,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Mac:
{
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
SetupDirectory(buildDir, true);
RunCmake(buildDir, platform, architecture, ".. -DCMAKE_BUILD_TYPE=Release");

View File

@@ -376,7 +376,7 @@ namespace Flax.Deps.Dependencies
GitCheckout(oggRoot, "master", "4380566a44b8d5e85ad511c9c17eb04197863ec5");
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
SetupDirectory(oggBuildDir, true);
RunCmake(oggBuildDir, platform, architecture, ".. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=\"../install\"");

View File

@@ -105,8 +105,7 @@ namespace Flax.Deps
if (totalBytes.HasValue)
progress.Update(totalBytesRead, totalBytes.Value);
}
}
while (hasMoreToRead);
} while (hasMoreToRead);
}
}
}

View File

@@ -96,7 +96,7 @@ namespace Flax.Deps
Console.WriteLine();
return false;
}
return true;
*/
}

View File

@@ -18,7 +18,7 @@ namespace Flax.Build.Platforms
public static readonly AndroidSdk Instance = new AndroidSdk();
/// <inheritdoc />
public override TargetPlatform[] Platforms => new []
public override TargetPlatform[] Platforms => new[]
{
TargetPlatform.Windows,
TargetPlatform.Linux,

View File

@@ -90,15 +90,15 @@ namespace Flax.Build.Platforms
/// Returns true if running an x64 binary an arm64 host machine.
/// </summary>
public unsafe static bool GetProcessIsTranslated()
{
int ret = 0;
ulong size = sizeof(int);
if (sysctlbyname("sysctl.proc_translated", &ret, &size, null, 0) == -1)
return false;
return ret != 0;
}
{
int ret = 0;
ulong size = sizeof(int);
if (sysctlbyname("sysctl.proc_translated", &ret, &size, null, 0) == -1)
return false;
return ret != 0;
}
[DllImport("c")]
private static unsafe extern int sysctlbyname(string name, void* oldp, ulong* oldlenp, void* newp, ulong newlen);
private static unsafe extern int sysctlbyname(string name, void* oldp, ulong* oldlenp, void* newp, ulong newlen);
}
}

View File

@@ -702,7 +702,7 @@ namespace Flax.Build.Projects.VisualStudio
{
// Build command for the build tool
var buildToolPath = Path.ChangeExtension(typeof(Builder).Assembly.Location, null);
var targetsFileContent = new StringBuilder();
targetsFileContent.AppendLine("<Project>");
targetsFileContent.AppendLine(" <!-- Custom Flax.Build scripts for C# projects. -->");

View File

@@ -410,8 +410,7 @@ namespace Flax.Build.Projects.VisualStudioCode
json.AddField("stopAtEntry", false);
json.AddField("externalConsole", true);
break;
case TargetPlatform.Linux:
break;
case TargetPlatform.Linux: break;
}
}
json.EndObject();
@@ -622,7 +621,7 @@ namespace Flax.Build.Projects.VisualStudioCode
json.AddField("**/Output", true);
json.AddField("**/*.flax", true);
json.EndObject();
// Extension settings
json.AddField("omnisharp.useModernNet", true);

View File

@@ -79,8 +79,7 @@ namespace Flax.Build
}
}
break;
default:
throw new InvalidPlatformException(buildData.Platform.Target);
default: throw new InvalidPlatformException(buildData.Platform.Target);
}
var result = sb.ToString();
BindingsGenerator.PutStringBuilder(sb);

View File

@@ -130,7 +130,7 @@ namespace Flax.Build
System = 0x00001000,
Task = 0x00002000
}
public enum Icon : uint
{
Warning = 0x00000030,