Skip to content

Commit

Permalink
Adding support for specifying a transparent struct kind
Browse files Browse the repository at this point in the history
  • Loading branch information
tannergooding committed Oct 31, 2021
1 parent 7dd1e00 commit 1467b0b
Show file tree
Hide file tree
Showing 7 changed files with 343 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2743,9 +2743,9 @@ private void VisitVarDecl(VarDecl varDecl)
{
flags |= ValueFlags.Copy;
}
else if (_config.WithTransparentStructs.TryGetValue(typeName, out var transparentValueTypeName))
else if (_config.WithTransparentStructs.TryGetValue(typeName, out var transparentStruct))
{
typeName = transparentValueTypeName;
typeName = transparentStruct.Name;
}
}
else if ((varDecl.StorageClass == CX_StorageClass.CX_SC_Static) || openedOutputBuilder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -702,9 +702,9 @@ private void VisitExplicitCastExpr(ExplicitCastExpr explicitCastExpr)
{
var cursorName = GetCursorName(varDecl);

if (cursorName.StartsWith("ClangSharpMacro_") && _config.WithTransparentStructs.TryGetValue(typeName, out var transparentValueTypeName))
if (cursorName.StartsWith("ClangSharpMacro_") && _config.WithTransparentStructs.TryGetValue(typeName, out var transparentStruct))
{
typeName = transparentValueTypeName;
typeName = transparentStruct.Name;
}
}

Expand Down
311 changes: 273 additions & 38 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ public sealed class PInvokeGeneratorConfiguration
private readonly Dictionary<string, IReadOnlyList<string>> _withAttributes;
private readonly Dictionary<string, string> _withCallConvs;
private readonly Dictionary<string, string> _withLibraryPaths;
private readonly Dictionary<string, string> _withTransparentStructs;
private readonly Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> _withTransparentStructs;
private readonly Dictionary<string, string> _withTypes;
private readonly Dictionary<string, IReadOnlyList<string>> _withUsings;

private PInvokeGeneratorConfigurationOptions _options;

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)
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)
{
if (excludedNames is null)
{
Expand Down Expand Up @@ -93,7 +93,7 @@ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, s
_withAttributes = new Dictionary<string, IReadOnlyList<string>>();
_withCallConvs = new Dictionary<string, string>();
_withLibraryPaths = new Dictionary<string, string>();
_withTransparentStructs = new Dictionary<string, string>();
_withTransparentStructs = new Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)>();
_withTypes = new Dictionary<string, string>();
_withUsings = new Dictionary<string, IReadOnlyList<string>>();

Expand Down Expand Up @@ -244,7 +244,7 @@ public bool ExcludeFnptrCodegen

public string[] WithSetLastErrors { get; }

public IReadOnlyDictionary<string, string> WithTransparentStructs => _withTransparentStructs;
public IReadOnlyDictionary<string, (string Name, PInvokeGeneratorTransparentStructKind Kind)> WithTransparentStructs => _withTransparentStructs;

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

Expand Down Expand Up @@ -324,6 +324,8 @@ private static AccessSpecifier ConvertStringToAccessSpecifier(string input)

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

private static (string, PInvokeGeneratorTransparentStructKind) RemoveAtPrefix((string Name, PInvokeGeneratorTransparentStructKind Kind) value) => (ValueStartsWithAt(value.Name) ? value.Name[1..] : value.Name, value.Kind);

private static bool ValueStartsWithAt(string value) => value.StartsWith("@");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace ClangSharp
{
public enum PInvokeGeneratorTransparentStructKind
{
Unknown = 0,
Typedef = 1,
Handle = 2,
Boolean = 3,
}
}
42 changes: 41 additions & 1 deletion sources/ClangSharpPInvokeGenerator/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public static int Run(InvocationContext context)
ParseKeyValuePairs(withAttributeNameValuePairs, errorList, out Dictionary<string, IReadOnlyList<string>> withAttributes);
ParseKeyValuePairs(withCallConvNameValuePairs, errorList, out Dictionary<string, string> withCallConvs);
ParseKeyValuePairs(withLibraryPathNameValuePairs, errorList, out Dictionary<string, string> withLibraryPath);
ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary<string, string> withTransparentStructs);
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);

Expand Down Expand Up @@ -631,6 +631,46 @@ private static void ParseKeyValuePairs(IEnumerable<string> keyValuePairs, List<s
}
}

private static void ParseKeyValuePairs(IEnumerable<string> keyValuePairs, List<string> errorList, out Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> result)
{
result = new Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)>();

foreach (var keyValuePair in keyValuePairs)
{
var parts = keyValuePair.Split('=');

if (parts.Length != 2)
{
errorList.Add($"Error: Invalid key/value pair argument: {keyValuePair}. Expected 'name=value' or 'name=value;kind'");
continue;
}

var key = parts[0].TrimEnd();

if (result.ContainsKey(key))
{
errorList.Add($"Error: A key with the given name already exists: {key}. Existing: {result[key]}");
continue;
}

parts = parts[1].Split(';');

if (parts.Length == 1)
{
result.Add(key, (parts[0], PInvokeGeneratorTransparentStructKind.Unknown));
}
else if ((parts.Length == 2) && Enum.TryParse<PInvokeGeneratorTransparentStructKind>(parts[1], out var transparentStructKind))
{
result.Add(key, (parts[0], transparentStructKind));
}
else
{
errorList.Add($"Error: Invalid key/value pair argument: {keyValuePair}. Expected 'name=value' or 'name=value;kind'");
continue;
}
}
}

private static void ParseKeyValuePairs(IEnumerable<string> keyValuePairs, List<string> errorList, out Dictionary<string, IReadOnlyList<string>> result)
{
result = new Dictionary<string, IReadOnlyList<string>>();
Expand Down
Loading

0 comments on commit 1467b0b

Please sign in to comment.