Skip to content

Commit 2e837ca

Browse files
committed
Adding support for specifying a transparent struct kind
1 parent 7dd1e00 commit 2e837ca

File tree

7 files changed

+343
-56
lines changed

7 files changed

+343
-56
lines changed

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2743,9 +2743,9 @@ private void VisitVarDecl(VarDecl varDecl)
27432743
{
27442744
flags |= ValueFlags.Copy;
27452745
}
2746-
else if (_config.WithTransparentStructs.TryGetValue(typeName, out var transparentValueTypeName))
2746+
else if (_config.WithTransparentStructs.TryGetValue(typeName, out var transparentStruct))
27472747
{
2748-
typeName = transparentValueTypeName;
2748+
typeName = transparentStruct.Name;
27492749
}
27502750
}
27512751
else if ((varDecl.StorageClass == CX_StorageClass.CX_SC_Static) || openedOutputBuilder)

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -702,9 +702,9 @@ private void VisitExplicitCastExpr(ExplicitCastExpr explicitCastExpr)
702702
{
703703
var cursorName = GetCursorName(varDecl);
704704

705-
if (cursorName.StartsWith("ClangSharpMacro_") && _config.WithTransparentStructs.TryGetValue(typeName, out var transparentValueTypeName))
705+
if (cursorName.StartsWith("ClangSharpMacro_") && _config.WithTransparentStructs.TryGetValue(typeName, out var transparentStruct))
706706
{
707-
typeName = transparentValueTypeName;
707+
typeName = transparentStruct.Name;
708708
}
709709
}
710710

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs

Lines changed: 273 additions & 38 deletions
Large diffs are not rendered by default.

sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ public sealed class PInvokeGeneratorConfiguration
1818
private readonly Dictionary<string, IReadOnlyList<string>> _withAttributes;
1919
private readonly Dictionary<string, string> _withCallConvs;
2020
private readonly Dictionary<string, string> _withLibraryPaths;
21-
private readonly Dictionary<string, string> _withTransparentStructs;
21+
private readonly Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> _withTransparentStructs;
2222
private readonly Dictionary<string, string> _withTypes;
2323
private readonly Dictionary<string, IReadOnlyList<string>> _withUsings;
2424

2525
private PInvokeGeneratorConfigurationOptions _options;
2626

27-
public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, string outputLocation, string testOutputLocation, PInvokeGeneratorOutputMode outputMode = PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions options = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, string headerFile = null, string methodClassName = null, string methodPrefixToStrip = null, IReadOnlyDictionary<string, string> remappedNames = null, string[] traversalNames = null, IReadOnlyDictionary<string, string> withAccessSpecifiers = null, IReadOnlyDictionary<string, IReadOnlyList<string>> withAttributes = null, IReadOnlyDictionary<string, string> withCallConvs = null, IReadOnlyDictionary<string, string> withLibraryPaths = null, string[] withSetLastErrors = null, IReadOnlyDictionary<string, string> withTransparentStructs = null, IReadOnlyDictionary<string, string> withTypes = null, IReadOnlyDictionary<string, IReadOnlyList<string>> withUsings = null)
27+
public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, string outputLocation, string testOutputLocation, PInvokeGeneratorOutputMode outputMode = PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions options = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, string headerFile = null, string methodClassName = null, string methodPrefixToStrip = null, IReadOnlyDictionary<string, string> remappedNames = null, string[] traversalNames = null, IReadOnlyDictionary<string, string> withAccessSpecifiers = null, IReadOnlyDictionary<string, IReadOnlyList<string>> withAttributes = null, IReadOnlyDictionary<string, string> withCallConvs = null, IReadOnlyDictionary<string, string> withLibraryPaths = null, string[] withSetLastErrors = null, IReadOnlyDictionary<string, (string, PInvokeGeneratorTransparentStructKind)> withTransparentStructs = null, IReadOnlyDictionary<string, string> withTypes = null, IReadOnlyDictionary<string, IReadOnlyList<string>> withUsings = null)
2828
{
2929
if (excludedNames is null)
3030
{
@@ -93,7 +93,7 @@ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, s
9393
_withAttributes = new Dictionary<string, IReadOnlyList<string>>();
9494
_withCallConvs = new Dictionary<string, string>();
9595
_withLibraryPaths = new Dictionary<string, string>();
96-
_withTransparentStructs = new Dictionary<string, string>();
96+
_withTransparentStructs = new Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)>();
9797
_withTypes = new Dictionary<string, string>();
9898
_withUsings = new Dictionary<string, IReadOnlyList<string>>();
9999

@@ -244,7 +244,7 @@ public bool ExcludeFnptrCodegen
244244

245245
public string[] WithSetLastErrors { get; }
246246

247-
public IReadOnlyDictionary<string, string> WithTransparentStructs => _withTransparentStructs;
247+
public IReadOnlyDictionary<string, (string Name, PInvokeGeneratorTransparentStructKind Kind)> WithTransparentStructs => _withTransparentStructs;
248248

249249
public IReadOnlyDictionary<string, string> WithTypes => _withTypes;
250250

@@ -324,6 +324,8 @@ private static AccessSpecifier ConvertStringToAccessSpecifier(string input)
324324

325325
private static string RemoveAtPrefix(string value) => ValueStartsWithAt(value) ? value[1..] : value;
326326

327+
private static (string, PInvokeGeneratorTransparentStructKind) RemoveAtPrefix((string Name, PInvokeGeneratorTransparentStructKind Kind) value) => (ValueStartsWithAt(value.Name) ? value.Name[1..] : value.Name, value.Kind);
328+
327329
private static bool ValueStartsWithAt(string value) => value.StartsWith("@");
328330
}
329331
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace ClangSharp
2+
{
3+
public enum PInvokeGeneratorTransparentStructKind
4+
{
5+
Unknown = 0,
6+
Typedef = 1,
7+
Handle = 2,
8+
Boolean = 3,
9+
}
10+
}

sources/ClangSharpPInvokeGenerator/Program.cs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ public static int Run(InvocationContext context)
186186
ParseKeyValuePairs(withAttributeNameValuePairs, errorList, out Dictionary<string, IReadOnlyList<string>> withAttributes);
187187
ParseKeyValuePairs(withCallConvNameValuePairs, errorList, out Dictionary<string, string> withCallConvs);
188188
ParseKeyValuePairs(withLibraryPathNameValuePairs, errorList, out Dictionary<string, string> withLibraryPath);
189-
ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary<string, string> withTransparentStructs);
189+
ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> withTransparentStructs);
190190
ParseKeyValuePairs(withTypeNameValuePairs, errorList, out Dictionary<string, string> withTypes);
191191
ParseKeyValuePairs(withUsingNameValuePairs, errorList, out Dictionary<string, IReadOnlyList<string>> withUsings);
192192

@@ -631,6 +631,46 @@ private static void ParseKeyValuePairs(IEnumerable<string> keyValuePairs, List<s
631631
}
632632
}
633633

634+
private static void ParseKeyValuePairs(IEnumerable<string> keyValuePairs, List<string> errorList, out Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> result)
635+
{
636+
result = new Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)>();
637+
638+
foreach (var keyValuePair in keyValuePairs)
639+
{
640+
var parts = keyValuePair.Split('=');
641+
642+
if (parts.Length != 2)
643+
{
644+
errorList.Add($"Error: Invalid key/value pair argument: {keyValuePair}. Expected 'name=value' or 'name=value;kind'");
645+
continue;
646+
}
647+
648+
var key = parts[0].TrimEnd();
649+
650+
if (result.ContainsKey(key))
651+
{
652+
errorList.Add($"Error: A key with the given name already exists: {key}. Existing: {result[key]}");
653+
continue;
654+
}
655+
656+
parts = parts[1].Split(';');
657+
658+
if (parts.Length == 1)
659+
{
660+
result.Add(key, (parts[0], PInvokeGeneratorTransparentStructKind.Unknown));
661+
}
662+
else if ((parts.Length == 2) && Enum.TryParse<PInvokeGeneratorTransparentStructKind>(parts[1], out var transparentStructKind))
663+
{
664+
result.Add(key, (parts[0], transparentStructKind));
665+
}
666+
else
667+
{
668+
errorList.Add($"Error: Invalid key/value pair argument: {keyValuePair}. Expected 'name=value' or 'name=value;kind'");
669+
continue;
670+
}
671+
}
672+
}
673+
634674
private static void ParseKeyValuePairs(IEnumerable<string> keyValuePairs, List<string> errorList, out Dictionary<string, IReadOnlyList<string>> result)
635675
{
636676
result = new Dictionary<string, IReadOnlyList<string>>();

0 commit comments

Comments
 (0)