Adding support for --with-pack-override

This commit is contained in:
Benjamin Moir 2022-10-28 23:15:34 +10:00
Родитель 57b5c0dc31
Коммит 0a72628f22
6 изменённых файлов: 45 добавлений и 4 удалений

Просмотреть файл

@ -111,6 +111,7 @@ internal struct StructDesc
public long Size32 { get; set; }
public long Size64 { get; set; }
public long Pack { get; set; }
public string? PackOverride { get; set; }
public long MaxFieldAlignment { get; set; }
public LayoutKind Kind { get; set; }
}

Просмотреть файл

@ -740,13 +740,18 @@ internal partial class CSharpOutputBuilder : IOutputBuilder
WriteLine("\"]/*' />");
}
if (desc.LayoutAttribute is not null)
if (desc.LayoutAttribute is not null || desc.Layout.PackOverride is not null)
{
AddUsingDirective("System.Runtime.InteropServices");
WriteIndented("[StructLayout(LayoutKind.");
Write(desc.LayoutAttribute.Value);
Write(desc.LayoutAttribute?.Value ?? LayoutKind.Sequential);
if (desc.LayoutAttribute.Pack != 0)
if (desc.Layout.PackOverride is { } packOverride)
{
Write(", Pack = ");
Write(packOverride);
}
else if (desc.LayoutAttribute!.Pack != 0)
{
Write(", Pack = ");
Write(desc.LayoutAttribute.Pack);

Просмотреть файл

@ -1479,6 +1479,7 @@ public partial class PInvokeGenerator
Size32 = size32,
Size64 = size64,
Pack = alignment < maxAlignm ? alignment : 0,
PackOverride = TryGetRemappedValue(recordDecl, _config.WithPackOverrides, out var packOverride) ? packOverride : null,
MaxFieldAlignment = maxAlignm,
Kind = layoutKind
},

Просмотреть файл

@ -45,6 +45,7 @@ public sealed class PInvokeGeneratorConfiguration
private readonly SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)> _withTransparentStructs;
private readonly SortedDictionary<string, string> _withTypes;
private readonly SortedDictionary<string, IReadOnlyList<string>> _withUsings;
private readonly SortedDictionary<string, string> _withPackOverrides;
private PInvokeGeneratorConfigurationOptions _options;
@ -94,6 +95,7 @@ public sealed class PInvokeGeneratorConfiguration
_withTransparentStructs = new SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)>();
_withTypes = new SortedDictionary<string, string>();
_withUsings = new SortedDictionary<string, IReadOnlyList<string>>();
_withPackOverrides = new SortedDictionary<string, string>();
if ((outputMode == PInvokeGeneratorOutputMode.Xml) && !options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) && (options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsNUnit) || options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsXUnit)))
{
@ -528,6 +530,20 @@ public sealed class PInvokeGeneratorConfiguration
}
}
[AllowNull]
public IReadOnlyDictionary<string, string> WithPackOverrides
{
get
{
return _withPackOverrides;
}
init
{
AddRange(_withPackOverrides, value);
}
}
public static AccessSpecifier ConvertStringToAccessSpecifier(string input)
{
if (input.Equals("internal", StringComparison.OrdinalIgnoreCase))

Просмотреть файл

@ -57,6 +57,7 @@ public class Program
private static readonly Option<string[]> s_withTransparentStructNameValuePairs;
private static readonly Option<string[]> s_withTypeNameValuePairs;
private static readonly Option<string[]> s_withUsingNameValuePairs;
private static readonly Option<string[]> s_withPackOverrideNameValuePairs;
private static readonly TwoColumnHelpRow[] s_configOptions = new TwoColumnHelpRow[]
@ -161,6 +162,7 @@ public class Program
s_withTransparentStructNameValuePairs = GetWithTransparentStructOption();
s_withTypeNameValuePairs = GetWithTypeOption();
s_withUsingNameValuePairs = GetWithUsingOption();
s_withPackOverrideNameValuePairs = GetWithPackOverrideOption();
s_rootCommand = new RootCommand("ClangSharp P/Invoke Binding Generator")
{
@ -198,7 +200,8 @@ public class Program
s_withSuppressGCTransitions,
s_withTransparentStructNameValuePairs,
s_withTypeNameValuePairs,
s_withUsingNameValuePairs
s_withUsingNameValuePairs,
s_withPackOverrideNameValuePairs
};
Handler.SetHandler(s_rootCommand, (Action<InvocationContext>)Run);
}
@ -255,6 +258,7 @@ public class Program
var withTransparentStructNameValuePairs = context.ParseResult.GetValueForOption(s_withTransparentStructNameValuePairs) ?? Array.Empty<string>();
var withTypeNameValuePairs = context.ParseResult.GetValueForOption(s_withTypeNameValuePairs) ?? Array.Empty<string>();
var withUsingNameValuePairs = context.ParseResult.GetValueForOption(s_withUsingNameValuePairs) ?? Array.Empty<string>();
var withPackOverrideNameValuePairs = context.ParseResult.GetValueForOption(s_withPackOverrideNameValuePairs) ?? Array.Empty<string>();
var versionResult = context.ParseResult.FindResultFor(s_versionOption);
@ -295,6 +299,7 @@ public class Program
ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> withTransparentStructs);
ParseKeyValuePairs(withTypeNameValuePairs, errorList, out Dictionary<string, string> withTypes);
ParseKeyValuePairs(withUsingNameValuePairs, errorList, out Dictionary<string, IReadOnlyList<string>> withUsings);
ParseKeyValuePairs(withPackOverrideNameValuePairs, errorList, out Dictionary<string, string> withPackOverrides);
foreach (var key in withTransparentStructs.Keys)
{
@ -681,6 +686,7 @@ public class Program
WithTransparentStructs = withTransparentStructs,
WithTypes = withTypes,
WithUsings = withUsings,
WithPackOverrides = withPackOverrides,
};
if (config.GenerateMacroBindings)
@ -1288,4 +1294,15 @@ public class Program
AllowMultipleArgumentsPerToken = true
};
}
private static Option<string[]> GetWithPackOverrideOption()
{
return new Option<string[]>(
aliases: new string[] { "--with-pack-override", "-wpo" },
description: "Overrides the StructLayoutAttribute.Pack property for the given type.",
getDefaultValue: Array.Empty<string>
) {
AllowMultipleArgumentsPerToken = true
};
}
}

Просмотреть файл

@ -106,6 +106,7 @@ public abstract class PInvokeGeneratorTest
WithTransparentStructs = withTransparentStructs,
WithTypes = withTypes,
WithUsings = withUsings,
WithPackOverrides = null,
};
using (var pinvokeGenerator = new PInvokeGenerator(config, (path) => outputStream))