diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs index 4981160f..f02c4ce6 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs @@ -124,7 +124,12 @@ private void VisitDecl(Decl decl) // case CX_DeclKind.CX_DeclKind_ClassTemplatePartialSpecialization: // case CX_DeclKind.CX_DeclKind_TemplateTypeParm: // case CX_DeclKind.CX_DeclKind_ObjCTypeParam: - // case CX_DeclKind.CX_DeclKind_TypeAlias: + + case CX_DeclKind.CX_DeclKind_TypeAlias: + { + VisitTypeAliasDecl((TypeAliasDecl)decl); + break; + } case CX_DeclKind.CX_DeclKind_Typedef: { @@ -2411,6 +2416,11 @@ private void VisitTranslationUnitDecl(TranslationUnitDecl translationUnitDecl) Visit(translationUnitDecl.CursorChildren, translationUnitDecl.Decls); } + private void VisitTypeAliasDecl(TypeAliasDecl typeAliasDecl) + { + // Nothing to generate for type alias declarations + } + private void VisitTypedefDecl(TypedefDecl typedefDecl) { ForUnderlyingType(typedefDecl, typedefDecl.UnderlyingType); @@ -3083,7 +3093,12 @@ private bool IsConstant(Expr initExpr) // case CX_StmtClass.CX_StmtClass_ObjCSelectorExpr: // case CX_StmtClass.CX_StmtClass_ObjCStringLiteral: // case CX_StmtClass.CX_StmtClass_ObjCSubscriptRefExpr: - // case CX_StmtClass.CX_StmtClass_OffsetOfExpr: + + case CX_StmtClass.CX_StmtClass_OffsetOfExpr: + { + return false; + } + // case CX_StmtClass.CX_StmtClass_OpaqueValueExpr: // case CX_StmtClass.CX_StmtClass_UnresolvedLookupExpr: // case CX_StmtClass.CX_StmtClass_UnresolvedMemberExpr: diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs index 88a38b26..8d12da68 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs @@ -109,6 +109,11 @@ private void VisitCallExpr(CallExpr callExpr) Visit(callExpr.Callee); VisitArgs(callExpr); } + else if (calleeDecl is VarDecl) + { + Visit(callExpr.Callee); + VisitArgs(callExpr); + } else { AddDiagnostic(DiagnosticLevel.Error, $"Unsupported callee declaration: '{calleeDecl?.DeclKindName}'. Generated bindings may be incomplete.", calleeDecl); @@ -1642,7 +1647,13 @@ private void VisitStmt(Stmt stmt) // case CX_StmtClass.CX_StmtClass_ObjCSelectorExpr: // case CX_StmtClass.CX_StmtClass_ObjCStringLiteral: // case CX_StmtClass.CX_StmtClass_ObjCSubscriptRefExpr: - // case CX_StmtClass.CX_StmtClass_OffsetOfExpr: + + case CX_StmtClass.CX_StmtClass_OffsetOfExpr: + { + VisitOffsetOfExpr((OffsetOfExpr)stmt); + break; + } + // case CX_StmtClass.CX_StmtClass_OpaqueValueExpr: case CX_StmtClass.CX_StmtClass_UnresolvedLookupExpr: @@ -2055,6 +2066,20 @@ private void VisitUnaryOperator(UnaryOperator unaryOperator) StopCSharpCode(); } + private void VisitOffsetOfExpr(OffsetOfExpr offsetOfExpr) + { + var outputBuilder = StartCSharpCode(); + + outputBuilder.AddUsingDirective("System.Runtime.InteropServices"); + outputBuilder.Write("Marshal.OffsetOf<"); + outputBuilder.Write(GetRemappedTypeName(offsetOfExpr, context: null, offsetOfExpr.TypeSourceInfoType, out var _)); + outputBuilder.Write(">(\""); + Visit(offsetOfExpr.Referenced); + outputBuilder.Write("\")"); + + StopCSharpCode(); + } + private void VisitUnresolvedLookupExpr(UnresolvedLookupExpr unresolvedLookupExpr) { var outputBuilder = StartCSharpCode(); diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs index ef3d5a71..47c779fd 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs @@ -1503,7 +1503,16 @@ private string GetTypeName(Cursor cursor, Cursor context, Type type, out string } else { - // The default name should be correct + // The default name should be correct for C++, but C may have a prefix we need to strip + + if (name.StartsWith("enum ")) + { + name = name.Substring(5); + } + else if (name.StartsWith("struct ")) + { + name = name.Substring(7); + } } if (name.Contains("::")) @@ -1629,6 +1638,10 @@ private string GetTypeNameForPointeeType(Cursor cursor, Cursor context, Type poi { name = GetTypeNameForPointeeType(cursor, context, attributedType.ModifiedType, out var nativeModifiedTypeName); } + else if (pointeeType is ElaboratedType elaboratedType) + { + name = GetTypeNameForPointeeType(cursor, context, elaboratedType.NamedType, out var nativeNamedTypeName); + } else if (pointeeType is FunctionType functionType) { if (!_config.ExcludeFnptrCodegen && (functionType is FunctionProtoType functionProtoType)) @@ -1728,6 +1741,24 @@ private string GetTypeNameForPointeeType(Cursor cursor, Cursor context, Type poi name = "IntPtr"; } } + else if (pointeeType is TypedefType typedefType) + { + // We check remapped names here so that types that have variable sizes + // can be treated correctly. Otherwise, they will resolve to a particular + // platform size, based on whatever parameters were passed into clang. + + var remappedName = GetRemappedName(name, cursor, tryRemapOperatorName: false, out var wasRemapped); + + if (wasRemapped) + { + name = remappedName; + name += '*'; + } + else + { + name = GetTypeNameForPointeeType(cursor, context, typedefType.Decl.UnderlyingType, out var nativeUnderlyingTypeName); + } + } else { // Otherwise fields that point at anonymous structs get the wrong name @@ -2983,7 +3014,12 @@ private bool IsUnchecked(string targetTypeName, Stmt stmt) // case CX_StmtClass.CX_StmtClass_ObjCSelectorExpr: // case CX_StmtClass.CX_StmtClass_ObjCStringLiteral: // case CX_StmtClass.CX_StmtClass_ObjCSubscriptRefExpr: - // case CX_StmtClass.CX_StmtClass_OffsetOfExpr: + + case CX_StmtClass.CX_StmtClass_OffsetOfExpr: + { + return false; + } + // case CX_StmtClass.CX_StmtClass_OpaqueValueExpr: // case CX_StmtClass.CX_StmtClass_UnresolvedLookupExpr: // case CX_StmtClass.CX_StmtClass_UnresolvedMemberExpr: diff --git a/sources/ClangSharp/Cursors/Decls/Decl.cs b/sources/ClangSharp/Cursors/Decls/Decl.cs index 80ac4800..1e4bb76d 100644 --- a/sources/ClangSharp/Cursors/Decls/Decl.cs +++ b/sources/ClangSharp/Cursors/Decls/Decl.cs @@ -167,7 +167,7 @@ public bool IsStdNamespace CX_DeclKind.CX_DeclKind_ObjCCategoryImpl => new ObjCCategoryImplDecl(handle), CX_DeclKind.CX_DeclKind_ObjCImplementation => new ObjCImplementationDecl(handle), CX_DeclKind.CX_DeclKind_ObjCInterface => new ObjCInterfaceDecl(handle), - CX_DeclKind.CX_DeclKind_ObjCProtocol => new ObjCPropertyDecl(handle), + CX_DeclKind.CX_DeclKind_ObjCProtocol => new ObjCProtocolDecl(handle), CX_DeclKind.CX_DeclKind_ObjCMethod => new ObjCMethodDecl(handle), CX_DeclKind.CX_DeclKind_ObjCProperty => new ObjCPropertyDecl(handle), CX_DeclKind.CX_DeclKind_BuiltinTemplate => new BuiltinTemplateDecl(handle), diff --git a/sources/ClangSharp/Cursors/Exprs/OffsetOfExpr.cs b/sources/ClangSharp/Cursors/Exprs/OffsetOfExpr.cs index 16540d4c..10735c9c 100644 --- a/sources/ClangSharp/Cursors/Exprs/OffsetOfExpr.cs +++ b/sources/ClangSharp/Cursors/Exprs/OffsetOfExpr.cs @@ -10,11 +10,13 @@ namespace ClangSharp public sealed class OffsetOfExpr : Expr { private readonly Lazy> _indexExprs; + private readonly Lazy _referenced; private readonly Lazy _typeSourceInfoType; internal OffsetOfExpr(CXCursor handle) : base(handle, CXCursorKind.CXCursor_UnexposedExpr, CX_StmtClass.CX_StmtClass_OffsetOfExpr) { _indexExprs = new Lazy>(() => Children.Cast().ToList()); + _referenced = new Lazy(() => TranslationUnit.GetOrCreate(Handle.Referenced)); _typeSourceInfoType = new Lazy(() => TranslationUnit.GetOrCreate(Handle.TypeOperand)); } @@ -22,6 +24,8 @@ internal OffsetOfExpr(CXCursor handle) : base(handle, CXCursorKind.CXCursor_Unex public uint NumExpressions => NumChildren; + public Cursor Referenced => _referenced.Value; + public Type TypeSourceInfoType => _typeSourceInfoType.Value; } } diff --git a/sources/ClangSharpPInvokeGenerator/Program.cs b/sources/ClangSharpPInvokeGenerator/Program.cs index a4786bab..284dfbc9 100644 --- a/sources/ClangSharpPInvokeGenerator/Program.cs +++ b/sources/ClangSharpPInvokeGenerator/Program.cs @@ -440,12 +440,23 @@ public static int Run(InvocationContext context) return -1; } - var clangCommandLineArgs = new string[] + string[] clangCommandLineArgs; + + if (string.IsNullOrWhiteSpace(std)) { - $"--language={language}", // Treat subsequent input files as having type - $"--std={std}", // Language standard to compile for - "-Wno-pragma-once-outside-header" // We are processing files which may be header files - }; + clangCommandLineArgs = new string[] { + $"--language={language}", // Treat subsequent input files as having type + "-Wno-pragma-once-outside-header" // We are processing files which may be header files + }; + } + else + { + clangCommandLineArgs = new string[] { + $"--language={language}", // Treat subsequent input files as having type + $"--std={std}", // Language standard to compile for + "-Wno-pragma-once-outside-header" // We are processing files which may be header files + }; + } clangCommandLineArgs = clangCommandLineArgs.Concat(includeDirectories.Select(x => "--include-directory=" + x)).ToArray(); clangCommandLineArgs = clangCommandLineArgs.Concat(defineMacros.Select(x => "--define-macro=" + x)).ToArray(); @@ -806,7 +817,7 @@ private static void AddStdOption(RootCommand rootCommand) aliases: new string[] { "--std", "-std" }, description: "Language standard to compile for.", argumentType: typeof(string), - getDefaultValue: () => "c++17", + getDefaultValue: () => "", arity: ArgumentArity.ExactlyOne ); diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/FunctionPointerDeclarationTest.cs index 02a40778..7ac0d785 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/FunctionPointerDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/FunctionPointerDeclarationTest.cs @@ -9,5 +9,8 @@ public abstract class FunctionPointerDeclarationTest : PInvokeGeneratorTest { [Fact] public abstract Task BasicTest(); + + [Fact] + public abstract Task PointerlessTypedefTest(); } } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/FunctionPointerDeclarationTest.cs index d6f172f7..3295a043 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/FunctionPointerDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/FunctionPointerDeclarationTest.cs @@ -8,14 +8,54 @@ public sealed class CSharpCompatibleUnix_FunctionPointerDeclarationTest : Functi { public override Task BasicTest() { - var inputContents = @"typedef void (*Callback)();"; + var inputContents = @"typedef void (*Callback)(); - var expectedOutputContents = @"using System.Runtime.InteropServices; +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @"using System; +using System.Runtime.InteropServices; namespace ClangSharp.Test { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void Callback(); + + public partial struct MyStruct + { + [NativeTypeName(""Callback"")] + public IntPtr _callback; + } +} +"; + + return ValidateGeneratedCSharpCompatibleUnixBindingsAsync(inputContents, expectedOutputContents); + } + + public override Task PointerlessTypedefTest() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void Callback(); + + public partial struct MyStruct + { + [NativeTypeName(""Callback *"")] + public IntPtr _callback; + } } "; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/FunctionPointerDeclarationTest.cs index ad49017a..6cce30cd 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/FunctionPointerDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/FunctionPointerDeclarationTest.cs @@ -8,14 +8,54 @@ public sealed class CSharpCompatibleWindows_FunctionPointerDeclarationTest : Fun { public override Task BasicTest() { - var inputContents = @"typedef void (*Callback)();"; + var inputContents = @"typedef void (*Callback)(); - var expectedOutputContents = @"using System.Runtime.InteropServices; +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @"using System; +using System.Runtime.InteropServices; namespace ClangSharp.Test { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void Callback(); + + public partial struct MyStruct + { + [NativeTypeName(""Callback"")] + public IntPtr _callback; + } +} +"; + + return ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + public override Task PointerlessTypedefTest() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void Callback(); + + public partial struct MyStruct + { + [NativeTypeName(""Callback *"")] + public IntPtr _callback; + } } "; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/FunctionPointerDeclarationTest.cs index 128a4654..3e0d3297 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/FunctionPointerDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/FunctionPointerDeclarationTest.cs @@ -8,9 +8,44 @@ public sealed class CSharpLatestUnix_FunctionPointerDeclarationTest : FunctionPo { public override Task BasicTest() { - var inputContents = @"typedef void (*Callback)();"; + var inputContents = @"typedef void (*Callback)(); - var expectedOutputContents = ""; +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; + + return ValidateGeneratedCSharpLatestUnixBindingsAsync(inputContents, expectedOutputContents); + } + + public override Task PointerlessTypedefTest() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback *"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; return ValidateGeneratedCSharpLatestUnixBindingsAsync(inputContents, expectedOutputContents); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/FunctionPointerDeclarationTest.cs index 47e551b6..054dd96f 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/FunctionPointerDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/FunctionPointerDeclarationTest.cs @@ -8,9 +8,44 @@ public sealed class CSharpLatestWindows_FunctionPointerDeclarationTest : Functio { public override Task BasicTest() { - var inputContents = @"typedef void (*Callback)();"; + var inputContents = @"typedef void (*Callback)(); - var expectedOutputContents = ""; +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; + + return ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + public override Task PointerlessTypedefTest() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback *"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; return ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CTest.cs new file mode 100644 index 00000000..f8645fb4 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CTest.cs @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft and Contributors. All rights reserved. Licensed under the University of Illinois/NCSA Open Source License. See LICENSE.txt in the project root for license information. + +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Xunit; + +namespace ClangSharp.UnitTests +{ + public sealed class CTest : PInvokeGeneratorTest + { + [Fact] + public Task BasicTest() + { + var inputContents = @"typedef enum MyEnum { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +} enum_t; + +typedef struct MyStruct { + enum_t _field; +} struct_t; +"; + string expectedOutputContents; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + } + + public partial struct MyStruct + { + [NativeTypeName(""enum_t"")] + public MyEnum _field; + } +} +"; + } + else + { + expectedOutputContents = @"namespace ClangSharp.Test +{ + [NativeTypeName(""unsigned int"")] + public enum MyEnum : uint + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + } + + public partial struct MyStruct + { + [NativeTypeName(""enum_t"")] + public MyEnum _field; + } +} +"; + } + + return ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents, commandlineArgs: DefaultCClangCommandLineArgs); + } + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs index 5b8f9164..1e0cd713 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs @@ -20,7 +20,13 @@ public abstract class PInvokeGeneratorTest | CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes // Implicit attributes should be visited | CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord; - protected static readonly string[] DefaultClangCommandLineArgs = new string[] + protected static readonly string[] DefaultCClangCommandLineArgs = new string[] + { + "-std=c17", // The input files should be compiled for C 17 + "-xc", // The input files are C + }; + + protected static readonly string[] DefaultCppClangCommandLineArgs = new string[] { "-std=c++17", // The input files should be compiled for C++ 17 "-xc++", // The input files are C++ @@ -50,7 +56,7 @@ private static async Task ValidateGeneratedBindingsAsync(string inputContents, s { Assert.True(File.Exists(DefaultInputFileName)); - commandlineArgs ??= DefaultClangCommandLineArgs; + commandlineArgs ??= DefaultCppClangCommandLineArgs; configOptions |= PInvokeGeneratorConfigurationOptions.GenerateMacroBindings; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/FunctionPointerDeclarationTest.cs index abea8fc0..6763bedf 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/FunctionPointerDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/FunctionPointerDeclarationTest.cs @@ -8,7 +8,39 @@ public sealed class XmlCompatibleUnix_FunctionPointerDeclarationTest : FunctionP { public override Task BasicTest() { - var inputContents = @"typedef void (*Callback)();"; + var inputContents = @"typedef void (*Callback)(); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @" + + + + void + + + + IntPtr + + + + +"; + + return ValidateGeneratedXmlCompatibleUnixBindingsAsync(inputContents, expectedOutputContents); + } + + public override Task PointerlessTypedefTest() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; var expectedOutputContents = @" @@ -16,6 +48,11 @@ public override Task BasicTest() void + + + IntPtr + + "; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/FunctionPointerDeclarationTest.cs index 547114d5..3eafe565 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/FunctionPointerDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/FunctionPointerDeclarationTest.cs @@ -8,7 +8,39 @@ public sealed class XmlCompatibleWindows_FunctionPointerDeclarationTest : Functi { public override Task BasicTest() { - var inputContents = @"typedef void (*Callback)();"; + var inputContents = @"typedef void (*Callback)(); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @" + + + + void + + + + IntPtr + + + + +"; + + return ValidateGeneratedXmlCompatibleWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + public override Task PointerlessTypedefTest() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; var expectedOutputContents = @" @@ -16,6 +48,11 @@ public override Task BasicTest() void + + + IntPtr + + "; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/FunctionPointerDeclarationTest.cs index a44ce5b5..d290e2db 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/FunctionPointerDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/FunctionPointerDeclarationTest.cs @@ -8,9 +8,48 @@ public sealed class XmlLatestUnix_FunctionPointerDeclarationTest : FunctionPoint { public override Task BasicTest() { - var inputContents = @"typedef void (*Callback)();"; + var inputContents = @"typedef void (*Callback)(); - var expectedOutputContents = ""; +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; + + return ValidateGeneratedXmlLatestUnixBindingsAsync(inputContents, expectedOutputContents); + } + + public override Task PointerlessTypedefTest() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; return ValidateGeneratedXmlLatestUnixBindingsAsync(inputContents, expectedOutputContents); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/FunctionPointerDeclarationTest.cs index 2c9214b9..91a60e24 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/FunctionPointerDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/FunctionPointerDeclarationTest.cs @@ -8,9 +8,48 @@ public sealed class XmlLatestWindows_FunctionPointerDeclarationTest : FunctionPo { public override Task BasicTest() { - var inputContents = @"typedef void (*Callback)();"; + var inputContents = @"typedef void (*Callback)(); - var expectedOutputContents = ""; +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; + + return ValidateGeneratedXmlLatestWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + public override Task PointerlessTypedefTest() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; return ValidateGeneratedXmlLatestWindowsBindingsAsync(inputContents, expectedOutputContents); }