diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
index 5dcf30fc..d9261e52 100644
--- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
+++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
@@ -362,7 +362,7 @@ static void GenerateNativeTypeNameAttribute(PInvokeGenerator generator)
sw.WriteLine();
sw.Write("namespace ");
- sw.WriteLine(generator.GetNamespace("NativeTypeName"));
+ sw.WriteLine(generator.GetNamespace("NativeTypeNameAttribute"));
sw.WriteLine('{');
sw.WriteLine(" /// Defines the type of a member as it was used in the native signature.");
@@ -449,11 +449,26 @@ static void GenerateTransparentStructs(PInvokeGenerator generator)
sw.WriteLine(config.HeaderText);
}
+ var targetNamespace = generator.GetNamespace(name);
+
sw.WriteLine("using System;");
+
+ if (kind == PInvokeGeneratorTransparentStructKind.HandleWin32)
+ {
+ var handleNamespace = generator.GetNamespace("HANDLE");
+
+ if (targetNamespace != handleNamespace)
+ {
+ sw.Write("using ");
+ sw.Write(handleNamespace);
+ sw.WriteLine(';');
+ }
+ }
+
sw.WriteLine();
sw.Write("namespace ");
- sw.WriteLine(generator.GetNamespace(name));
+ sw.WriteLine(targetNamespace);
sw.WriteLine('{');
sw.Write(" public ");
@@ -3577,7 +3592,9 @@ bool IsExcludedByName(Cursor cursor, ref uint isExcludedValue)
}
}
- if (_config.ExcludedNames.Contains(qualifiedName) || _config.ExcludedNames.Contains(qualifiedName.Replace("::", ".")))
+ var dottedQualifiedName = qualifiedName.Replace("::", ".");
+
+ if (_config.ExcludedNames.Contains(qualifiedName) || _config.ExcludedNames.Contains(dottedQualifiedName))
{
if (_config.LogExclusions)
{
@@ -3626,6 +3643,15 @@ bool IsExcludedByName(Cursor cursor, ref uint isExcludedValue)
return true;
}
+ if ((_config.IncludedNames.Length != 0) && !_config.IncludedNames.Contains(qualifiedName) && !_config.IncludedNames.Contains(dottedQualifiedName) && !_config.IncludedNames.Contains(name))
+ {
+ if (_config.LogExclusions)
+ {
+ AddDiagnostic(DiagnosticLevel.Info, $"Excluded {kind} '{qualifiedName}' as it was not in the include list");
+ }
+ return true;
+ }
+
if ((isExcludedValue & 0b10) != 0)
{
if (_config.LogExclusions)
diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs
index a97b2460..ad61527f 100644
--- a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs
+++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs
@@ -25,13 +25,18 @@ public sealed class PInvokeGeneratorConfiguration
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 remappedNames = null, string[] traversalNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null)
+ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, string outputLocation, string testOutputLocation, PInvokeGeneratorOutputMode outputMode = PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions options = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, string[] includedNames = null, string headerFile = null, string methodClassName = null, string methodPrefixToStrip = null, IReadOnlyDictionary remappedNames = null, string[] traversalNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null)
{
if (excludedNames is null)
{
excludedNames = Array.Empty();
}
+ if (includedNames is null)
+ {
+ includedNames = Array.Empty();
+ }
+
if (string.IsNullOrWhiteSpace(libraryPath))
{
libraryPath = string.Empty;
@@ -101,6 +106,7 @@ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, s
ExcludedNames = excludedNames;
HeaderText = string.IsNullOrWhiteSpace(headerFile) ? string.Empty : File.ReadAllText(headerFile);
+ IncludedNames = includedNames;
LibraryPath = $@"""{libraryPath}""";
MethodClassName = methodClassName;
MethodPrefixToStrip = methodPrefixToStrip;
@@ -153,6 +159,8 @@ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, s
public string[] ExcludedNames { get; }
+ public string[] IncludedNames { get; }
+
public bool GenerateAggressiveInlining => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateAggressiveInlining);
public bool GenerateCompatibleCode => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode);
diff --git a/sources/ClangSharpPInvokeGenerator/Program.cs b/sources/ClangSharpPInvokeGenerator/Program.cs
index dafe167b..c2a038c1 100644
--- a/sources/ClangSharpPInvokeGenerator/Program.cs
+++ b/sources/ClangSharpPInvokeGenerator/Program.cs
@@ -97,6 +97,7 @@ public static async Task Main(params string[] args)
AddFileOption(s_rootCommand);
AddFileDirectoryOption(s_rootCommand);
AddHeaderOption(s_rootCommand);
+ AddIncludeOption(s_rootCommand);
AddIncludeDirectoryOption(s_rootCommand);
AddLanguageOption(s_rootCommand);
AddLibraryOption(s_rootCommand);
@@ -133,6 +134,7 @@ public static int Run(InvocationContext context)
var files = context.ParseResult.ValueForOption("--file");
var fileDirectory = context.ParseResult.ValueForOption("--file-directory");
var headerFile = context.ParseResult.ValueForOption("--headerFile");
+ var includedNames = context.ParseResult.ValueForOption("--include");
var includeDirectories = context.ParseResult.ValueForOption("--include-directory");
var language = context.ParseResult.ValueForOption("--language");
var libraryPath = context.ParseResult.ValueForOption("--libraryPath");
@@ -530,7 +532,7 @@ public static int Run(InvocationContext context)
translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes; // Include attributed types in CXType
translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes; // Implicit attributes should be visited
- var config = new PInvokeGeneratorConfiguration(libraryPath, namespaceName, outputLocation, testOutputLocation, outputMode, configOptions, excludedNames, headerFile, methodClassName, methodPrefixToStrip, remappedNames, traversalNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPath, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings);
+ var config = new PInvokeGeneratorConfiguration(libraryPath, namespaceName, outputLocation, testOutputLocation, outputMode, configOptions, excludedNames, includedNames, headerFile, methodClassName, methodPrefixToStrip, remappedNames, traversalNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPath, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings);
if (config.GenerateMacroBindings)
{
@@ -810,6 +812,19 @@ private static void AddHeaderOption(RootCommand rootCommand)
rootCommand.AddOption(option);
}
+ private static void AddIncludeOption(RootCommand rootCommand)
+ {
+ var option = new Option(
+ aliases: new string[] { "--include", "-i" },
+ description: "A declaration name to include in binding generation.",
+ argumentType: typeof(string),
+ getDefaultValue: Array.Empty,
+ arity: ArgumentArity.OneOrMore
+ );
+
+ rootCommand.AddOption(option);
+ }
+
private static void AddIncludeDirectoryOption(RootCommand rootCommand)
{
var option = new Option(
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs
index ec6fdada..518c572b 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs
@@ -64,7 +64,7 @@ private static async Task ValidateGeneratedBindingsAsync(string inputContents, s
using var unsavedFile = CXUnsavedFile.Create(DefaultInputFileName, inputContents);
var unsavedFiles = new CXUnsavedFile[] { unsavedFile };
- var config = new PInvokeGeneratorConfiguration(libraryPath, DefaultNamespaceName, Path.GetRandomFileName(), testOutputLocation: null, outputMode, configOptions, excludedNames, headerFile: null, methodClassName: null, methodPrefixToStrip: null, remappedNames, traversalNames: null, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings);
+ var config = new PInvokeGeneratorConfiguration(libraryPath, DefaultNamespaceName, Path.GetRandomFileName(), testOutputLocation: null, outputMode, configOptions, excludedNames, includedNames: null, headerFile: null, methodClassName: null, methodPrefixToStrip: null, remappedNames, traversalNames: null, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings);
using (var pinvokeGenerator = new PInvokeGenerator(config, (path) => outputStream))
{