Impl progress on c++ name mangling on Clang for proper P/Invokes binding

This commit is contained in:
Wojtek Figat
2023-01-24 17:31:09 +01:00
parent 35ea0b5447
commit 20c32ea6ed
3 changed files with 97 additions and 17 deletions

View File

@@ -18,6 +18,7 @@ namespace Flax.Build.Bindings
private static readonly List<string> CSharpAdditionalCode = new List<string>();
private static readonly Dictionary<string, string> CSharpAdditionalCodeCache = new Dictionary<string, string>();
#if USE_NETCORE
private static readonly TypeInfo CSharpEventBindReturn = new TypeInfo("void");
private static readonly List<FunctionInfo.ParameterInfo> CSharpEventBindParams = new List<FunctionInfo.ParameterInfo>() { new FunctionInfo.ParameterInfo() { Name = "bind", Type = new TypeInfo("bool") } };
#endif
@@ -1009,7 +1010,7 @@ namespace Flax.Build.Bindings
if (buildData.Toolchain.Compiler == TargetCompiler.MSVC)
libraryEntryPoint = $"{classInfo.FullNameManaged}::Internal_{eventInfo.Name}_Bind"; // MSVC allows to override exported symbol name
else
libraryEntryPoint = CppNameMangling.MangleFunctionName(buildData, eventInfo.Name + "_ManagedBind", classInfo.FullNameNativeInternal + "Internal", CSharpEventBindParams);
libraryEntryPoint = CppNameMangling.MangleFunctionName(buildData, eventInfo.Name + "_ManagedBind", classInfo.FullNameNativeInternal + "Internal", CSharpEventBindReturn, CSharpEventBindParams);
contents.Append(indent).Append($"[LibraryImport(\"{classInfo.ParentModule.Module.BinaryModuleName}\", EntryPoint = \"{libraryEntryPoint}\", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]").AppendLine();
contents.Append(indent).Append($"internal static partial void Internal_{eventInfo.Name}_Bind(");
if (!eventInfo.IsStatic)

View File

@@ -947,10 +947,7 @@ namespace Flax.Build.Bindings
{
Name = "__returnCount",
DefaultValue = "var __returnCount",
Type = new TypeInfo
{
Type = "int"
},
Type = new TypeInfo("int"),
IsOut = true,
});
}
@@ -969,7 +966,7 @@ namespace Flax.Build.Bindings
}
else
{
libraryEntryPoint = CppNameMangling.MangleFunctionName(buildData, functionInfo.Name, callerName, functionInfo.Parameters, functionInfo.Glue.CustomParameters);
libraryEntryPoint = CppNameMangling.MangleFunctionName(buildData, functionInfo.Name, callerName, functionInfo.ReturnType, functionInfo.IsStatic ? null : new TypeInfo(caller.Name) { IsPtr = true }, functionInfo.Parameters, functionInfo.Glue.CustomParameters);
useSeparateImpl = true; // DLLEXPORT doesn't properly export function thus separate implementation from declaration
}
functionInfo.Glue.LibraryEntryPoint = libraryEntryPoint;

View File

@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using System.Text;
using System.Collections.Generic;
using Flax.Build.Bindings;
@@ -11,19 +12,30 @@ namespace Flax.Build
/// </summary>
internal static class CppNameMangling
{
public static string MangleFunctionName(Builder.BuildData buildData, string name, string outerName, List<FunctionInfo.ParameterInfo> parameters1, List<FunctionInfo.ParameterInfo> parameters2)
public static string MangleFunctionName(Builder.BuildData buildData, string name, string outerName, TypeInfo returnType, TypeInfo parameter0, List<FunctionInfo.ParameterInfo> parameters1, List<FunctionInfo.ParameterInfo> parameters2)
{
if (parameters1 == null || parameters1.Count == 0)
return MangleFunctionName(buildData, name, outerName, parameters2);
if (parameters2 == null || parameters2.Count == 0)
return MangleFunctionName(buildData, name, outerName, parameters1);
var parameters = new List<FunctionInfo.ParameterInfo>();
parameters.AddRange(parameters1);
parameters.AddRange(parameters2);
return MangleFunctionName(buildData, name, outerName, parameters);
List<FunctionInfo.ParameterInfo> parameters = null;
if (parameter0 == null)
{
if (parameters1 == null || parameters1.Count == 0)
parameters = parameters2;
else if (parameters2 == null || parameters2.Count == 0)
parameters = parameters1;
}
if (parameters == null)
{
parameters = new List<FunctionInfo.ParameterInfo>();
if (parameter0 != null)
parameters.Add(new FunctionInfo.ParameterInfo() { Type = parameter0 });
if (parameters1 != null)
parameters.AddRange(parameters1);
if (parameters2 != null)
parameters.AddRange(parameters2);
}
return MangleFunctionName(buildData, name, outerName, returnType, parameters);
}
public static string MangleFunctionName(Builder.BuildData buildData, string name, string outerName, List<FunctionInfo.ParameterInfo> parameters)
public static string MangleFunctionName(Builder.BuildData buildData, string name, string outerName, TypeInfo returnType, List<FunctionInfo.ParameterInfo> parameters)
{
if (name.Contains(":"))
throw new NotImplementedException("No nested types mangling support.");
@@ -42,7 +54,28 @@ namespace Flax.Build
// TODO: mangle parameters
break;
case TargetCompiler.Clang:
sb.Append("todo");
// References:
// http://web.mit.edu/tibbetts/Public/inside-c/www/mangling.html
// https://en.wikipedia.org/wiki/Name_mangling
sb.Append("_ZN");
//if (!returnType.IsVoid)
// MangleTypeClang(sb, returnType);
sb.Append(outerName.Length);
sb.Append(outerName);
sb.Append(name.Length);
sb.Append(name);
sb.Append('E');
if (parameters == null || parameters.Count == 0)
{
sb.Append('v');
}
else
{
foreach (var e in parameters)
{
MangleTypeClang(sb, e.Type);
}
}
break;
default:
throw new InvalidPlatformException(buildData.Platform.Target);
@@ -51,5 +84,54 @@ namespace Flax.Build
BindingsGenerator.PutStringBuilder(sb);
return result;
}
private static void MangleTypeClang(StringBuilder sb, TypeInfo type)
{
if (type.IsPtr)
sb.Append('P');
if (type.IsRef)
sb.Append('R');
if (type.IsConst)
sb.Append('K');
switch (type.Type)
{
// TODO: use proper typedef extraction from TypedefInfo
case "Float2":
sb.Append("11Vector2BaseIfE");
break;
case "Float3":
sb.Append("11Vector3BaseIfE");
break;
case "Float4":
sb.Append("11Vector4BaseIfE");
break;
case "bool":
sb.Append('b');
break;
case "char":
case "int8":
sb.Append('c');
break;
case "int":
case "int32":
sb.Append('i');
break;
case "float":
sb.Append('f');
break;
default:
sb.Append(type.Type.Length);
sb.Append(type.Type);
if (type.GenericArgs != null)
{
sb.Append('I');
foreach (var e in type.GenericArgs)
MangleTypeClang(sb, e);
sb.Append('E');
}
break;
}
}
}
}