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 Size32 { get; set; }
public long Size64 { get; set; } public long Size64 { get; set; }
public long Pack { get; set; } public long Pack { get; set; }
public string? PackOverride { get; set; }
public long MaxFieldAlignment { get; set; } public long MaxFieldAlignment { get; set; }
public LayoutKind Kind { get; set; } public LayoutKind Kind { get; set; }
} }

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

@ -740,13 +740,18 @@ internal partial class CSharpOutputBuilder : IOutputBuilder
WriteLine("\"]/*' />"); WriteLine("\"]/*' />");
} }
if (desc.LayoutAttribute is not null) if (desc.LayoutAttribute is not null || desc.Layout.PackOverride is not null)
{ {
AddUsingDirective("System.Runtime.InteropServices"); AddUsingDirective("System.Runtime.InteropServices");
WriteIndented("[StructLayout(LayoutKind."); 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(", Pack = ");
Write(desc.LayoutAttribute.Pack); Write(desc.LayoutAttribute.Pack);

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

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

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

@ -45,6 +45,7 @@ public sealed class PInvokeGeneratorConfiguration
private readonly SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)> _withTransparentStructs; private readonly SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)> _withTransparentStructs;
private readonly SortedDictionary<string, string> _withTypes; private readonly SortedDictionary<string, string> _withTypes;
private readonly SortedDictionary<string, IReadOnlyList<string>> _withUsings; private readonly SortedDictionary<string, IReadOnlyList<string>> _withUsings;
private readonly SortedDictionary<string, string> _withPackOverrides;
private PInvokeGeneratorConfigurationOptions _options; private PInvokeGeneratorConfigurationOptions _options;
@ -94,6 +95,7 @@ public sealed class PInvokeGeneratorConfiguration
_withTransparentStructs = new SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)>(); _withTransparentStructs = new SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)>();
_withTypes = new SortedDictionary<string, string>(); _withTypes = new SortedDictionary<string, string>();
_withUsings = new SortedDictionary<string, IReadOnlyList<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))) 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) public static AccessSpecifier ConvertStringToAccessSpecifier(string input)
{ {
if (input.Equals("internal", StringComparison.OrdinalIgnoreCase)) 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_withTransparentStructNameValuePairs;
private static readonly Option<string[]> s_withTypeNameValuePairs; private static readonly Option<string[]> s_withTypeNameValuePairs;
private static readonly Option<string[]> s_withUsingNameValuePairs; private static readonly Option<string[]> s_withUsingNameValuePairs;
private static readonly Option<string[]> s_withPackOverrideNameValuePairs;
private static readonly TwoColumnHelpRow[] s_configOptions = new TwoColumnHelpRow[] private static readonly TwoColumnHelpRow[] s_configOptions = new TwoColumnHelpRow[]
@ -161,6 +162,7 @@ public class Program
s_withTransparentStructNameValuePairs = GetWithTransparentStructOption(); s_withTransparentStructNameValuePairs = GetWithTransparentStructOption();
s_withTypeNameValuePairs = GetWithTypeOption(); s_withTypeNameValuePairs = GetWithTypeOption();
s_withUsingNameValuePairs = GetWithUsingOption(); s_withUsingNameValuePairs = GetWithUsingOption();
s_withPackOverrideNameValuePairs = GetWithPackOverrideOption();
s_rootCommand = new RootCommand("ClangSharp P/Invoke Binding Generator") s_rootCommand = new RootCommand("ClangSharp P/Invoke Binding Generator")
{ {
@ -198,7 +200,8 @@ public class Program
s_withSuppressGCTransitions, s_withSuppressGCTransitions,
s_withTransparentStructNameValuePairs, s_withTransparentStructNameValuePairs,
s_withTypeNameValuePairs, s_withTypeNameValuePairs,
s_withUsingNameValuePairs s_withUsingNameValuePairs,
s_withPackOverrideNameValuePairs
}; };
Handler.SetHandler(s_rootCommand, (Action<InvocationContext>)Run); 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 withTransparentStructNameValuePairs = context.ParseResult.GetValueForOption(s_withTransparentStructNameValuePairs) ?? Array.Empty<string>();
var withTypeNameValuePairs = context.ParseResult.GetValueForOption(s_withTypeNameValuePairs) ?? Array.Empty<string>(); var withTypeNameValuePairs = context.ParseResult.GetValueForOption(s_withTypeNameValuePairs) ?? Array.Empty<string>();
var withUsingNameValuePairs = context.ParseResult.GetValueForOption(s_withUsingNameValuePairs) ?? 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); var versionResult = context.ParseResult.FindResultFor(s_versionOption);
@ -295,6 +299,7 @@ public class Program
ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> withTransparentStructs); ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> withTransparentStructs);
ParseKeyValuePairs(withTypeNameValuePairs, errorList, out Dictionary<string, string> withTypes); ParseKeyValuePairs(withTypeNameValuePairs, errorList, out Dictionary<string, string> withTypes);
ParseKeyValuePairs(withUsingNameValuePairs, errorList, out Dictionary<string, IReadOnlyList<string>> withUsings); ParseKeyValuePairs(withUsingNameValuePairs, errorList, out Dictionary<string, IReadOnlyList<string>> withUsings);
ParseKeyValuePairs(withPackOverrideNameValuePairs, errorList, out Dictionary<string, string> withPackOverrides);
foreach (var key in withTransparentStructs.Keys) foreach (var key in withTransparentStructs.Keys)
{ {
@ -681,6 +686,7 @@ public class Program
WithTransparentStructs = withTransparentStructs, WithTransparentStructs = withTransparentStructs,
WithTypes = withTypes, WithTypes = withTypes,
WithUsings = withUsings, WithUsings = withUsings,
WithPackOverrides = withPackOverrides,
}; };
if (config.GenerateMacroBindings) if (config.GenerateMacroBindings)
@ -1288,4 +1294,15 @@ public class Program
AllowMultipleArgumentsPerToken = true 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, WithTransparentStructs = withTransparentStructs,
WithTypes = withTypes, WithTypes = withTypes,
WithUsings = withUsings, WithUsings = withUsings,
WithPackOverrides = null,
}; };
using (var pinvokeGenerator = new PInvokeGenerator(config, (path) => outputStream)) using (var pinvokeGenerator = new PInvokeGenerator(config, (path) => outputStream))