Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Naming.cs
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,16 @@ private string GetRemappedTypeName(Cursor? cursor, Cursor? context, Type type, o
nativeTypeName = string.Empty;
}

if (TryLowerFixedSizeBufferRemapping(remappedName, out var loweredName))
{
remappedName = loweredName;
}

return remappedName;
}

private static bool TryLowerFixedSizeBufferRemapping(string remappedName, out string loweredName)
{
if (remappedName.IndexOf('[', StringComparison.Ordinal) is int bracketIndex and >= 0 &&
(bracketIndex + 1) < remappedName.Length && char.IsAsciiDigit(remappedName[bracketIndex + 1]))
{
Expand All @@ -822,10 +832,12 @@ private string GetRemappedTypeName(Cursor? cursor, Cursor? context, Type type, o
// A managed array such as `int[]` has an empty subscript and is left untouched.

var rank = remappedName.AsSpan().Count('[');
remappedName = string.Concat(remappedName.AsSpan(0, bracketIndex), new string('*', rank));
loweredName = string.Concat(remappedName.AsSpan(0, bracketIndex), new string('*', rank));
return true;
}

return remappedName;
loweredName = remappedName;
return false;
}
}

14 changes: 14 additions & 0 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,20 @@ static ReadOnlySpan<char> GetFoundRemappingString(ReadOnlySpan<char> name, HashS
return result;
}
}

if (_config.LogInvalidRemappings)
{
foreach (var kvp in _config._remappedNames)
{
var name = kvp.Key;
var remappedName = kvp.Value;

if (TryLowerFixedSizeBufferRemapping(remappedName, out var loweredName))
{
AddDiagnostic(DiagnosticLevel.Info, $"Potential invalid remapping '{name}={remappedName}'. A fixed-size-buffer type is not directly expressible in an unmanaged signature; it was lowered to the pointer '{loweredName}'.");
}
}
}
}
catch (Exception e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ public string LibraryPath

public bool LogPotentialTypedefRemappings => (_options & PInvokeGeneratorConfigurationOptions.LogPotentialTypedefRemappings) != 0;

public bool LogInvalidRemappings => (_options & PInvokeGeneratorConfigurationOptions.LogInvalidRemappings) != 0;

public bool LogVisitedFiles => (_options & PInvokeGeneratorConfigurationOptions.LogVisitedFiles) != 0;

[AllowNull]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,6 @@ public enum PInvokeGeneratorConfigurationOptions : long
DontUseUsingStaticsForGuidMember = 1L << 40,

GenerateFixedBufferIndexerOverloads = 1L << 41,

LogInvalidRemappings = 1L << 42,
}
1 change: 1 addition & 0 deletions sources/ClangSharpPInvokeGenerator/Program.Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ internal static partial class Program
new TwoColumnHelpRow("", ""),

new TwoColumnHelpRow("log-exclusions", "A list of excluded declaration types should be generated. This will also log if the exclusion was due to an exact or partial match."),
new TwoColumnHelpRow("log-invalid-remappings", "A diagnostic should be generated for each remapping whose value is not directly expressible in an unmanaged signature, such as a fixed-size-buffer shape that was lowered to a pointer."),
new TwoColumnHelpRow("log-potential-typedef-remappings", "A list of potential typedef remappings should be generated. This can help identify missing remappings."),
new TwoColumnHelpRow("log-visited-files", "A list of the visited files should be generated. This can help identify traversal issues."),
];
Expand Down
6 changes: 6 additions & 0 deletions sources/ClangSharpPInvokeGenerator/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,12 @@ public static void Run(InvocationContext context)
break;
}

case "log-invalid-remappings":
{
configOptions |= PInvokeGeneratorConfigurationOptions.LogInvalidRemappings;
break;
}

case "log-potential-typedef-remappings":
{
configOptions |= PInvokeGeneratorConfigurationOptions.LogPotentialTypedefRemappings;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.

using System.Collections.Generic;
using System.Threading.Tasks;
using NUnit.Framework;

namespace ClangSharp.UnitTests;

public sealed class LogInvalidRemappingsTest : PInvokeGeneratorTest
{
[Test]
public Task FixedSizeBufferRemappingIsLoggedAndLoweredToPointer()
{
var inputContents = @"typedef int MyBuffer;

extern ""C"" void MyFunction(MyBuffer value);
extern ""C"" MyBuffer MyOtherFunction();";

var expectedOutputContents = @"using System.Runtime.InteropServices;

namespace ClangSharp.Test
{
public static unsafe partial class Methods
{
[DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void MyFunction([NativeTypeName(""MyBuffer"")] sbyte* value);

[DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: NativeTypeName(""MyBuffer"")]
public static extern sbyte* MyOtherFunction();
}
}
";

var remappedNames = new Dictionary<string, string> {
["MyBuffer"] = "sbyte[8]"
};

var expectedDiagnostics = new[] {
new Diagnostic(DiagnosticLevel.Info, "Potential invalid remapping 'MyBuffer=sbyte[8]'. A fixed-size-buffer type is not directly expressible in an unmanaged signature; it was lowered to the pointer 'sbyte*'.")
};

return ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents, additionalConfigOptions: PInvokeGeneratorConfigurationOptions.LogInvalidRemappings, remappedNames: remappedNames, expectedDiagnostics: expectedDiagnostics);
}
}
Loading