From 82e41d3601c3ffab6d7a3f747620c3a63744664c Mon Sep 17 00:00:00 2001 From: AlexR Date: Sat, 20 Apr 2019 21:34:33 +0400 Subject: [PATCH] Fix a crash when a function pointer takes a function pointer Fixes https://github.com/mono/CppSharp/issues/1144 --- src/Generator/Generators/CSharp/CSharpTypePrinter.cs | 9 ++++++++- src/Generator/Passes/DelegatesPass.cs | 9 +++++++++ tests/CSharp/CSharp.Tests.cs | 2 ++ tests/CSharp/CSharp.h | 1 + 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index 24321b7e..630dcd43 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -276,7 +276,14 @@ namespace CppSharp.Generators.CSharp return typeMap.CSharpSignatureType(typePrinterContext).ToString(); } - FunctionType func = decl.Type as FunctionType; + FunctionType func; + if (decl.Type.IsPointerTo(out func)) + { + if (MarshalKind == MarshalKind.GenericDelegate && ContextKind == TypePrinterContextKind.Native) + return VisitDeclaration(decl); + } + + func = decl.Type as FunctionType; if (func != null || decl.Type.IsPointerTo(out func)) { if (ContextKind == TypePrinterContextKind.Native) diff --git a/src/Generator/Passes/DelegatesPass.cs b/src/Generator/Passes/DelegatesPass.cs index de1914d9..1c503fc3 100644 --- a/src/Generator/Passes/DelegatesPass.cs +++ b/src/Generator/Passes/DelegatesPass.cs @@ -94,6 +94,9 @@ namespace CppSharp.Passes public override bool VisitParameterDecl(Parameter parameter) { + if(parameter.Namespace?.TranslationUnit?.Module == null && namespaces.Count > 0) + parameter.Namespace = namespaces.Peek(); + if (!base.VisitDeclaration(parameter) || parameter.Namespace == null || parameter.Namespace.Ignore) return false; @@ -117,12 +120,17 @@ namespace CppSharp.Passes public override bool VisitFieldDecl(Field field) { + if (field.Namespace?.TranslationUnit?.Module != null) + namespaces.Push(field.Namespace); + if (!base.VisitFieldDecl(field)) return false; field.QualifiedType = CheckForDelegate(field.QualifiedType, field.Namespace); + namespaces.Clear(); + return true; } @@ -297,5 +305,6 @@ namespace CppSharp.Passes /// iterating over it, so we collect all the typedefs and add them at the end. /// private readonly List delegates = new List(); + private readonly Stack namespaces = new Stack(); } } diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/CSharp/CSharp.Tests.cs index bbe82114..3be409a5 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/tests/CSharp/CSharp.Tests.cs @@ -1268,6 +1268,8 @@ public unsafe class CSharpTests : GeneratorTestFixture { hasFunctionPtrField.FunctionPtrField = @string => @string.Length; Assert.That(hasFunctionPtrField.FunctionPtrField("Test"), Is.EqualTo(4)); + hasFunctionPtrField.FunctionPtrTakeFunctionPtrField = field => field(); + Assert.That(hasFunctionPtrField.FunctionPtrTakeFunctionPtrField(() => 42), Is.EqualTo(42)); } } diff --git a/tests/CSharp/CSharp.h b/tests/CSharp/CSharp.h index 13d1c671..9c283fd5 100644 --- a/tests/CSharp/CSharp.h +++ b/tests/CSharp/CSharp.h @@ -1301,6 +1301,7 @@ public: HasFunctionPtrField(); ~HasFunctionPtrField(); int (*functionPtrField)(const char*); + int (*functionPtrTakeFunctionPtrField)(int(*TakenInFuncPtrField)()); }; DLL_API void va_listFunction(va_list v);