Skip to content

Commit 2218939

Browse files
Merge pull request #405 from DaZombieKiller/with-pack-override
Add support for --with-packing
2 parents 57b5c0d + 35ca8a3 commit 2218939

File tree

7 files changed

+56
-21
lines changed

7 files changed

+56
-21
lines changed

sources/ClangSharp.PInvokeGenerator/Abstractions/StructDesc.cs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,12 @@ public StructLayoutAttribute? LayoutAttribute
8383
{
8484
Debug.Assert(layout.Kind == LayoutKind.Explicit);
8585

86-
var attribute = new StructLayoutAttribute(layout.Kind);
87-
88-
if (layout.Pack != 0)
89-
{
90-
attribute.Pack = (int)layout.Pack;
91-
}
92-
93-
return attribute;
86+
return new StructLayoutAttribute(layout.Kind);
9487
}
9588

96-
if (layout.Pack != 0)
89+
if (layout.Pack is not null)
9790
{
98-
return new StructLayoutAttribute(layout.Kind) {
99-
Pack = (int)layout.Pack
100-
};
91+
return new StructLayoutAttribute(layout.Kind);
10192
}
10293

10394
return null;
@@ -110,7 +101,7 @@ public struct LayoutDesc
110101
public long Alignment64 { get; set; }
111102
public long Size32 { get; set; }
112103
public long Size64 { get; set; }
113-
public long Pack { get; set; }
104+
public string? Pack { get; set; }
114105
public long MaxFieldAlignment { get; set; }
115106
public LayoutKind Kind { get; set; }
116107
}

sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,10 +746,10 @@ public void BeginStruct(in StructDesc desc)
746746
WriteIndented("[StructLayout(LayoutKind.");
747747
Write(desc.LayoutAttribute.Value);
748748

749-
if (desc.LayoutAttribute.Pack != 0)
749+
if (desc.Layout.Pack is not null)
750750
{
751751
Write(", Pack = ");
752-
Write(desc.LayoutAttribute.Pack);
752+
Write(desc.Layout.Pack);
753753
}
754754

755755
WriteLine(")]");

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,11 @@ private void VisitRecordDecl(RecordDecl recordDecl)
14671467
baseTypeNames = baseTypeNamesBuilder.ToArray();
14681468
}
14691469

1470+
if (!TryGetRemappedValue(recordDecl, _config.WithPackings, out var pack))
1471+
{
1472+
pack = alignment < maxAlignm ? alignment.ToString(CultureInfo.InvariantCulture) : null;
1473+
}
1474+
14701475
var desc = new StructDesc {
14711476
AccessSpecifier = GetAccessSpecifier(recordDecl, matchStar: true),
14721477
EscapedName = escapedName,
@@ -1478,7 +1483,7 @@ private void VisitRecordDecl(RecordDecl recordDecl)
14781483
Alignment64 = alignment64,
14791484
Size32 = size32,
14801485
Size64 = size64,
1481-
Pack = alignment < maxAlignm ? alignment : 0,
1486+
Pack = pack,
14821487
MaxFieldAlignment = maxAlignm,
14831488
Kind = layoutKind
14841489
},
@@ -1515,7 +1520,7 @@ private void VisitRecordDecl(RecordDecl recordDecl)
15151520

15161521
if (desc.LayoutAttribute is not null)
15171522
{
1518-
withAttributes.Add($"StructLayout(LayoutKind.{desc.LayoutAttribute.Value}{((desc.LayoutAttribute.Pack != 0) ? $", Pack = {desc.LayoutAttribute.Pack}" : "")})");
1523+
withAttributes.Add($"StructLayout(LayoutKind.{desc.LayoutAttribute.Value}{((desc.Layout.Pack is not null) ? $", Pack = {desc.Layout.Pack}" : "")})");
15191524
_ = withUsings.Add("System.Runtime.InteropServices");
15201525
}
15211526

@@ -2817,6 +2822,11 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
28172822
AddDiagnostic(DiagnosticLevel.Info, $"{escapedName} (constant array field) has a size of 0", constantOrIncompleteArray);
28182823
}
28192824

2825+
if (!TryGetRemappedValue(recordDecl, _config.WithPackings, out var pack))
2826+
{
2827+
pack = alignment < maxAlignm ? alignment.ToString(CultureInfo.InvariantCulture) : null;
2828+
}
2829+
28202830
var desc = new StructDesc {
28212831
AccessSpecifier = accessSpecifier,
28222832
EscapedName = escapedName,
@@ -2826,7 +2836,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
28262836
Alignment64 = alignment64,
28272837
Size32 = size32,
28282838
Size64 = size64,
2829-
Pack = alignment < maxAlignm ? alignment : 0,
2839+
Pack = pack,
28302840
MaxFieldAlignment = maxAlignm,
28312841
Kind = LayoutKind.Sequential
28322842
},

sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public sealed class PInvokeGeneratorConfiguration
4545
private readonly SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)> _withTransparentStructs;
4646
private readonly SortedDictionary<string, string> _withTypes;
4747
private readonly SortedDictionary<string, IReadOnlyList<string>> _withUsings;
48+
private readonly SortedDictionary<string, string> _withPackings;
4849

4950
private PInvokeGeneratorConfigurationOptions _options;
5051

@@ -94,6 +95,7 @@ public PInvokeGeneratorConfiguration(string defaultNamespace, string outputLocat
9495
_withTransparentStructs = new SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)>();
9596
_withTypes = new SortedDictionary<string, string>();
9697
_withUsings = new SortedDictionary<string, IReadOnlyList<string>>();
98+
_withPackings = new SortedDictionary<string, string>();
9799

98100
if ((outputMode == PInvokeGeneratorOutputMode.Xml) && !options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) && (options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsNUnit) || options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsXUnit)))
99101
{
@@ -528,6 +530,20 @@ public IReadOnlyDictionary<string, IReadOnlyList<string>> WithUsings
528530
}
529531
}
530532

533+
[AllowNull]
534+
public IReadOnlyDictionary<string, string> WithPackings
535+
{
536+
get
537+
{
538+
return _withPackings;
539+
}
540+
541+
init
542+
{
543+
AddRange(_withPackings, value);
544+
}
545+
}
546+
531547
public static AccessSpecifier ConvertStringToAccessSpecifier(string input)
532548
{
533549
if (input.Equals("internal", StringComparison.OrdinalIgnoreCase))

sources/ClangSharp.PInvokeGenerator/XML/XmlOutputBuilder.VisitDecl.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,10 +290,10 @@ public void BeginStruct(in StructDesc info)
290290
_ = _sb.Append(info.LayoutAttribute.Value);
291291
_ = _sb.Append('"');
292292

293-
if (info.LayoutAttribute.Pack != 0)
293+
if (info.Layout.Pack is not null)
294294
{
295295
_ = _sb.Append(" pack=\"");
296-
_ = _sb.Append(info.LayoutAttribute.Pack);
296+
_ = _sb.Append(info.Layout.Pack);
297297
_ = _sb.Append('"');
298298
}
299299
}

sources/ClangSharpPInvokeGenerator/Program.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public class Program
5757
private static readonly Option<string[]> s_withTransparentStructNameValuePairs;
5858
private static readonly Option<string[]> s_withTypeNameValuePairs;
5959
private static readonly Option<string[]> s_withUsingNameValuePairs;
60+
private static readonly Option<string[]> s_withPackingNameValuePairs;
6061

6162

6263
private static readonly TwoColumnHelpRow[] s_configOptions = new TwoColumnHelpRow[]
@@ -161,6 +162,7 @@ static Program()
161162
s_withTransparentStructNameValuePairs = GetWithTransparentStructOption();
162163
s_withTypeNameValuePairs = GetWithTypeOption();
163164
s_withUsingNameValuePairs = GetWithUsingOption();
165+
s_withPackingNameValuePairs = GetWithPackingOption();
164166

165167
s_rootCommand = new RootCommand("ClangSharp P/Invoke Binding Generator")
166168
{
@@ -198,7 +200,8 @@ static Program()
198200
s_withSuppressGCTransitions,
199201
s_withTransparentStructNameValuePairs,
200202
s_withTypeNameValuePairs,
201-
s_withUsingNameValuePairs
203+
s_withUsingNameValuePairs,
204+
s_withPackingNameValuePairs
202205
};
203206
Handler.SetHandler(s_rootCommand, (Action<InvocationContext>)Run);
204207
}
@@ -255,6 +258,7 @@ public static void Run(InvocationContext context)
255258
var withTransparentStructNameValuePairs = context.ParseResult.GetValueForOption(s_withTransparentStructNameValuePairs) ?? Array.Empty<string>();
256259
var withTypeNameValuePairs = context.ParseResult.GetValueForOption(s_withTypeNameValuePairs) ?? Array.Empty<string>();
257260
var withUsingNameValuePairs = context.ParseResult.GetValueForOption(s_withUsingNameValuePairs) ?? Array.Empty<string>();
261+
var withPackingNameValuePairs = context.ParseResult.GetValueForOption(s_withPackingNameValuePairs) ?? Array.Empty<string>();
258262

259263
var versionResult = context.ParseResult.FindResultFor(s_versionOption);
260264

@@ -295,6 +299,7 @@ public static void Run(InvocationContext context)
295299
ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> withTransparentStructs);
296300
ParseKeyValuePairs(withTypeNameValuePairs, errorList, out Dictionary<string, string> withTypes);
297301
ParseKeyValuePairs(withUsingNameValuePairs, errorList, out Dictionary<string, IReadOnlyList<string>> withUsings);
302+
ParseKeyValuePairs(withPackingNameValuePairs, errorList, out Dictionary<string, string> withPackings);
298303

299304
foreach (var key in withTransparentStructs.Keys)
300305
{
@@ -681,6 +686,7 @@ public static void Run(InvocationContext context)
681686
WithTransparentStructs = withTransparentStructs,
682687
WithTypes = withTypes,
683688
WithUsings = withUsings,
689+
WithPackings = withPackings,
684690
};
685691

686692
if (config.GenerateMacroBindings)
@@ -1288,4 +1294,15 @@ private static Option<string[]> GetWithUsingOption()
12881294
AllowMultipleArgumentsPerToken = true
12891295
};
12901296
}
1297+
1298+
private static Option<string[]> GetWithPackingOption()
1299+
{
1300+
return new Option<string[]>(
1301+
aliases: new string[] { "--with-packing", "-wp" },
1302+
description: "Overrides the StructLayoutAttribute.Pack property for the given type.",
1303+
getDefaultValue: Array.Empty<string>
1304+
) {
1305+
AllowMultipleArgumentsPerToken = true
1306+
};
1307+
}
12911308
}

tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ private static async Task ValidateGeneratedBindingsAsync(string inputContents, s
106106
WithTransparentStructs = withTransparentStructs,
107107
WithTypes = withTypes,
108108
WithUsings = withUsings,
109+
WithPackings = null,
109110
};
110111

111112
using (var pinvokeGenerator = new PInvokeGenerator(config, (path) => outputStream))

0 commit comments

Comments
 (0)