From 172f8fbf5d2c65dbb437c038d57ae0f8b68ad546 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Tue, 15 Apr 2014 17:06:26 +0200 Subject: [PATCH 1/9] Ignore function types to non-static member functions. --- src/Generator/Types/Types.cs | 11 +++++++++++ tests/Basic/Basic.h | 6 +++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Generator/Types/Types.cs b/src/Generator/Types/Types.cs index 3549fb63..8d1393d9 100644 --- a/src/Generator/Types/Types.cs +++ b/src/Generator/Types/Types.cs @@ -127,6 +127,17 @@ namespace CppSharp Ignore(); return base.VisitTemplateSpecializationType(template, quals); + } + + public override bool VisitFunctionType(FunctionType function, TypeQualifiers quals) + { + // We don't know how to marshal non-static member functions + if (function.CallingConvention == CallingConvention.ThisCall) + { + Ignore(); + return false; + } + return base.VisitFunctionType(function, quals); } } diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index d839385c..b47d7471 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -243,12 +243,16 @@ typedef int (*DelegateInGlobalNamespace)(int); struct DLL_API TestDelegates { typedef int (*DelegateInClass)(int); + typedef int(TestDelegates::*MemberDelegate)(int); - TestDelegates() : A(Double), B(Double) {} + TestDelegates() : A(Double), B(Double) { C = &TestDelegates::Triple; } static int Double(int N) { return N * 2; } + int Triple(int N) { return N * 3; } DelegateInClass A; DelegateInGlobalNamespace B; + // As long as we can't marshal them make sure they're ignored + MemberDelegate C; }; // Tests memory leaks in constructors From d8b855bfe6b908ab6b5656acd86918b8887b42f8 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Tue, 15 Apr 2014 21:23:49 +0200 Subject: [PATCH 2/9] Fixed handling of primitive pointer types. --- src/AST/TypeExtensions.cs | 28 +++++++++++++++++++ src/Generator/Generators/CLI/CLIMarshal.cs | 8 +++--- .../Generators/CLI/CLITypePrinter.cs | 24 ++++++++++------ .../Generators/CSharp/CSharpTypePrinter.cs | 22 ++++++++++----- tests/Basic/Basic.Tests.cs | 12 +++++++- tests/Basic/Basic.cpp | 5 ++++ tests/Basic/Basic.h | 6 +++- 7 files changed, 84 insertions(+), 21 deletions(-) diff --git a/src/AST/TypeExtensions.cs b/src/AST/TypeExtensions.cs index 9165713f..837c47f7 100644 --- a/src/AST/TypeExtensions.cs +++ b/src/AST/TypeExtensions.cs @@ -154,6 +154,34 @@ } return t; + } + + public static Type GetFinalPointee(this PointerType pointer) + { + var pointee = pointer.Pointee; + while (pointee.IsPointer()) + { + var p = pointee as PointerType; + if (p != null) + pointee = p.Pointee; + else + return GetFinalPointee(pointee as MemberPointerType); + } + return pointee; + } + + public static Type GetFinalPointee(this MemberPointerType pointer) + { + var pointee = pointer.Pointee; + while (pointee.IsPointer()) + { + var p = pointee as MemberPointerType; + if (p != null) + pointee = p.Pointee; + else + return GetFinalPointee(pointee as PointerType); + } + return pointee; } } } \ No newline at end of file diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 45eda0ca..a1f5d75f 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -427,10 +427,10 @@ namespace CppSharp.Generators.CLI if (Context.Function == null) Context.Return.Write("&"); return pointee.Visit(this, quals); - } - - PrimitiveType primitive; - if (pointee.IsPrimitiveType(out primitive)) + } + + var finalPointee = pointer.GetFinalPointee(); + if (finalPointee.IsPrimitiveType()) { var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypeName = pointer.Visit(cppTypePrinter, quals); diff --git a/src/Generator/Generators/CLI/CLITypePrinter.cs b/src/Generator/Generators/CLI/CLITypePrinter.cs index 9875cfbe..c97210b1 100644 --- a/src/Generator/Generators/CLI/CLITypePrinter.cs +++ b/src/Generator/Generators/CLI/CLITypePrinter.cs @@ -140,16 +140,24 @@ namespace CppSharp.Generators.CLI if (pointee.IsPrimitiveType(PrimitiveType.Char) && quals.IsConst) { return "System::String^"; - } - - PrimitiveType primitive; - if (pointee.Desugar().IsPrimitiveType(out primitive)) + } + + // From http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx + // Any of the following types may be a pointer type: + // * sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool. + // * Any enum type. + // * Any pointer type. + // * Any user-defined struct type that contains fields of unmanaged types only. + var finalPointee = pointer.GetFinalPointee(); + if (finalPointee.IsPrimitiveType()) { - var param = Context.Parameter; - if (param != null && (param.IsOut || param.IsInOut)) - return VisitPrimitiveType(primitive); + // Skip one indirection if passed by reference + var param = Context.Parameter; + if (param != null && (param.IsOut || param.IsInOut) + && pointee == finalPointee) + return pointee.Visit(this, quals); - return VisitPrimitiveType(primitive, quals) + "*"; + return pointee.Visit(this, quals) + "*"; } return pointee.Visit(this, quals); diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index b0c098fb..dfdef8b0 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -208,21 +208,29 @@ namespace CppSharp.Generators.CSharp if (IsConstCharString(pointer)) return isManagedContext ? "string" : "global::System.IntPtr"; - PrimitiveType primitive; - var desugared = pointee.Desugar(); - if (desugared.IsPrimitiveType(out primitive)) + // From http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx + // Any of the following types may be a pointer type: + // * sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool. + // * Any enum type. + // * Any pointer type. + // * Any user-defined struct type that contains fields of unmanaged types only. + var finalPointee = pointer.GetFinalPointee(); + if (finalPointee.IsPrimitiveType()) { - if (isManagedContext && Context.Parameter != null && - (Context.Parameter.IsOut || Context.Parameter.IsInOut)) - return VisitPrimitiveType(primitive, quals); + // Skip one indirection if passed by reference + var param = Context.Parameter; + if (isManagedContext && param != null && (param.IsOut || param.IsInOut) + && pointee == finalPointee) + return pointee.Visit(this, quals); if (ContextKind == CSharpTypePrinterContextKind.GenericDelegate) return "global::System.IntPtr"; - return VisitPrimitiveType(primitive, quals) + "*"; + return pointee.Visit(this, quals) + "*"; } Class @class; + var desugared = pointee.Desugar(); if ((desugared.IsDependent || desugared.IsTagDecl(out @class)) && ContextKind == CSharpTypePrinterContextKind.Native) { diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index 19095bb0..4f410326 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -22,7 +22,17 @@ public class BasicTests : GeneratorTestFixture Assert.That(hello.AddFoo(foo), Is.EqualTo(11)); Assert.That(hello.AddFooPtr(foo), Is.EqualTo(11)); Assert.That(hello.AddFooPtr(foo), Is.EqualTo(11)); - Assert.That(hello.AddFooRef(foo), Is.EqualTo(11)); + Assert.That(hello.AddFooRef(foo), Is.EqualTo(11)); + unsafe + { + var pointer = foo.SomePointer; + var pointerPointer = foo.SomePointerPointer; + for (int i = 0; i < 4; i++) + { + Assert.AreEqual(i, pointer[i]); + Assert.AreEqual(i, (*pointerPointer)[i]); + } + } var bar = new Bar { A = 4, B = 7 }; Assert.That(hello.AddBar(bar), Is.EqualTo(11)); diff --git a/tests/Basic/Basic.cpp b/tests/Basic/Basic.cpp index 54237caf..15fd7369 100644 --- a/tests/Basic/Basic.cpp +++ b/tests/Basic/Basic.cpp @@ -2,6 +2,11 @@ Foo::Foo() { + auto p = new int[4]; + for (int i = 0; i < 4; i++) + p[i] = i; + SomePointer = p; + SomePointerPointer = &SomePointer; } const char* Foo::GetANSI() diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index b47d7471..23fd08c8 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -18,7 +18,11 @@ public: // TODO: VC++ does not support char16 // char16 chr16; - float nested_array[2][2]; + // Not properly handled yet - ignore + float nested_array[2][2]; + // Primitive pointer types + int* SomePointer; + int** SomePointerPointer; }; struct DLL_API Bar From e6cb543c36860b717b2f32c6b059a504f94a8086 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Tue, 15 Apr 2014 22:27:48 +0200 Subject: [PATCH 3/9] Fixed overloading of an indexed properties by removing the hard coded "int index" part. --- .../Generators/CLI/CLIHeadersTemplate.cs | 15 +++--- .../Generators/CLI/CLISourcesTemplate.cs | 46 ++++++++++--------- .../Passes/CheckOperatorsOverloads.cs | 7 +-- tests/Basic/Basic.Tests.cs | 3 +- tests/Basic/Basic.h | 1 + 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs index 4654ab81..ef1c6adb 100644 --- a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs +++ b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs @@ -615,16 +615,19 @@ namespace CppSharp.Generators.CLI public void GenerateIndexer(Property property) { - var type = property.QualifiedType.Visit(TypePrinter); + var type = property.QualifiedType.Visit(TypePrinter); + var getter = property.GetMethod; + var indexParameter = getter.Parameters[0]; + var indexParameterType = indexParameter.QualifiedType.Visit(TypePrinter); - WriteLine("property {0} default[int]", type); + WriteLine("property {0} default[{1}]", type, indexParameterType); WriteStartBraceIndent(); - if (property.HasGetter) - WriteLine("{0} get(int index);", type); + if (property.HasGetter) + WriteLine("{0} get({1} {2});", type, indexParameterType, indexParameter.Name); - if (property.HasSetter) - WriteLine("void set(int index, {0});", type); + if (property.HasSetter) + WriteLine("void set({1} {2}, {0} value);", type, indexParameterType, indexParameter.Name); WriteCloseBraceIndent(); } diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index 1102ff97..a6281968 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -329,36 +329,37 @@ namespace CppSharp.Generators.CLI GeneratePropertyGetter(property.GetMethod, realOwner, property.Name, property.Type); - if (property.HasSetter) - GeneratePropertySetter(property.SetMethod, realOwner, property.Name, - property.Type); + if (property.HasSetter) + if (property.IsIndexer) + GeneratePropertySetter(property.SetMethod, realOwner, property.Name, + property.Type, property.GetMethod.Parameters[0]); + else + GeneratePropertySetter(property.SetMethod, realOwner, property.Name, + property.Type); } PopBlock(); - } - - private void GeneratePropertySetter(T decl, Class @class, string name, Type type) + } + + private void GeneratePropertySetter(T decl, Class @class, string name, Type type, Parameter indexParameter = null) where T : Declaration, ITypedDecl { if (decl == null) - return; + return; - var method = decl as Method; - var isIndexer = method != null && - method.OperatorKind == CXXOperatorKind.Subscript; - - var args = new List(); - if (isIndexer) - args.Add("int index"); + var args = new List(); + var isIndexer = indexParameter != null; + if (isIndexer) + args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name)); var function = decl as Function; - var argName = function != null ? function.Parameters[0].Name : "value"; + var argName = function != null && !isIndexer ? function.Parameters[0].Name : "value"; args.Add(string.Format("{0} {1}", type, argName)); WriteLine("void {0}::{1}::set({2})", QualifiedIdentifier(@class), name, string.Join(", ", args)); - WriteStartBraceIndent(); - + WriteStartBraceIndent(); + if (decl is Function && !isIndexer) { var func = decl as Function; @@ -397,7 +398,7 @@ namespace CppSharp.Generators.CLI @class.QualifiedOriginalName, decl.OriginalName); if (isIndexer) - variable += "(index)"; + variable += string.Format("({0})", indexParameter.Name); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) Write(marshal.Context.SupportBefore); @@ -419,9 +420,12 @@ namespace CppSharp.Generators.CLI var isIndexer = method != null && method.OperatorKind == CXXOperatorKind.Subscript; - var args = new List(); - if (isIndexer) - args.Add("int index"); + var args = new List(); + if (isIndexer) + { + var indexParameter = method.Parameters[0]; + args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name)); + } WriteLine("{0} {1}::{2}::get({3})", type, QualifiedIdentifier(@class), name, string.Join(", ", args)); diff --git a/src/Generator/Passes/CheckOperatorsOverloads.cs b/src/Generator/Passes/CheckOperatorsOverloads.cs index 841bcd5b..50bd0ecd 100644 --- a/src/Generator/Passes/CheckOperatorsOverloads.cs +++ b/src/Generator/Passes/CheckOperatorsOverloads.cs @@ -102,12 +102,7 @@ namespace CppSharp.Passes // C++/CLI uses "default" as the indexer property name. if (Driver.Options.IsCLIGenerator) - property.Name = "default"; - - property.GetMethod.Parameters[0].Name = "index"; - - if (property.SetMethod != null) - property.SetMethod.Parameters[0].Name = "index"; + property.Name = "default"; property.Parameters.AddRange(@operator.Parameters); diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index 4f410326..0ad5c6b7 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -233,7 +233,8 @@ public class BasicTests : GeneratorTestFixture public unsafe void TestIndexers() { var someStruct = new SomeStruct(); - Assert.That(someStruct[0], Is.EqualTo(1)); + Assert.That(someStruct[0], Is.EqualTo(1)); + Assert.That(someStruct["foo"], Is.EqualTo(1)); } [Test] diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 23fd08c8..7a8162bb 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -317,6 +317,7 @@ typedef struct DLL_API SomeStruct SomeStruct() : p(1) {} const foo_t& operator[](int i) const { return p; } foo_t operator[](int i) { return p; } + foo_t operator[](const char* name) { return p; } foo_t p; } SomeStruct; From 570f13112bedfbc5b5103c83cdf985390b32b749 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Wed, 16 Apr 2014 00:58:29 +0200 Subject: [PATCH 4/9] Fixed issue with const pointer. --- src/Generator/Generators/CLI/CLIMarshal.cs | 14 +++++++++----- tests/Basic/Basic.h | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index a1f5d75f..ae211ec5 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -90,12 +90,16 @@ namespace CppSharp.Generators.CLI } if (pointee.IsPrimitiveType(out primitive)) - { + { + var returnVarName = Context.ReturnVarName; + if (quals.IsConst != Context.ReturnType.Qualifiers.IsConst) + returnVarName = string.Format("const_cast<{0}>({1})", + Context.ReturnType, Context.ReturnVarName); if (pointer.Pointee is TypedefType) - Context.Return.Write("reinterpret_cast<{0}>({1})", pointer, - Context.ReturnVarName); - else - Context.Return.Write(Context.ReturnVarName); + Context.Return.Write("reinterpret_cast<{0}>({1})", pointer, + returnVarName); + else + Context.Return.Write(returnVarName); return true; } diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 7a8162bb..4a836261 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -21,8 +21,8 @@ public: // Not properly handled yet - ignore float nested_array[2][2]; // Primitive pointer types - int* SomePointer; - int** SomePointerPointer; + const int* SomePointer; + const int** SomePointerPointer; }; struct DLL_API Bar From f091c6662a400847e9bd092948aae60460a72d12 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Wed, 16 Apr 2014 01:03:31 +0200 Subject: [PATCH 5/9] CLI generator will use the pointee type for indexed properties which have a setter. --- src/Generator/Passes/CheckOperatorsOverloads.cs | 13 +++++++++++-- tests/Basic/Basic.Tests.cs | 4 +++- tests/Basic/Basic.h | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Generator/Passes/CheckOperatorsOverloads.cs b/src/Generator/Passes/CheckOperatorsOverloads.cs index 50bd0ecd..22564dd6 100644 --- a/src/Generator/Passes/CheckOperatorsOverloads.cs +++ b/src/Generator/Passes/CheckOperatorsOverloads.cs @@ -100,9 +100,18 @@ namespace CppSharp.Passes if (!@operator.ReturnType.Qualifiers.IsConst && @operator.ReturnType.Type.IsAddress()) property.SetMethod = @operator; - // C++/CLI uses "default" as the indexer property name. if (Driver.Options.IsCLIGenerator) - property.Name = "default"; + { + // If we've a setter use the pointee as the type of the property. + var pointerType = property.Type as PointerType; + if (pointerType != null && property.HasSetter) + { + property.QualifiedType = new QualifiedType(pointerType.Pointee, property.QualifiedType.Qualifiers); + property.GetMethod.ReturnType = property.QualifiedType; + } + // C++/CLI uses "default" as the indexer property name. + property.Name = "default"; + } property.Parameters.AddRange(@operator.Parameters); diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index 0ad5c6b7..fc289418 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -234,7 +234,9 @@ public class BasicTests : GeneratorTestFixture { var someStruct = new SomeStruct(); Assert.That(someStruct[0], Is.EqualTo(1)); - Assert.That(someStruct["foo"], Is.EqualTo(1)); + Assert.That(someStruct["foo"], Is.EqualTo(1)); + someStruct[0] = 2; + Assert.That(someStruct[0], Is.EqualTo(2)); } [Test] diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 4a836261..29012b47 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -315,8 +315,8 @@ typedef unsigned long foo_t; typedef struct DLL_API SomeStruct { SomeStruct() : p(1) {} - const foo_t& operator[](int i) const { return p; } - foo_t operator[](int i) { return p; } + foo_t& operator[](int i) { return p; } + // CSharp backend can't deal with a setter here foo_t operator[](const char* name) { return p; } foo_t p; } From 3144976349a5340460caab8c0f325d3be3541294 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Wed, 16 Apr 2014 15:58:31 +0200 Subject: [PATCH 6/9] Removed unnecessary Desugar() calls when testing whether or not a type is primitive. The extension method IsPrimitiveType does the desugaring - see 55bbba46dd68f4a9ed35a399e2ad407004521849. --- src/Generator/Generators/CLI/CLIMarshal.cs | 2 +- src/Generator/Generators/CLI/CLISourcesTemplate.cs | 2 +- src/Generator/Generators/CSharp/CSharpTextTemplate.cs | 4 ++-- src/Generator/Passes/CheckIgnoredDecls.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index ae211ec5..75672601 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -501,7 +501,7 @@ namespace CppSharp.Generators.CLI } PrimitiveType primitive; - if (decl.Type.Desugar().IsPrimitiveType(out primitive)) + if (decl.Type.IsPrimitiveType(out primitive)) { Context.Return.Write("(::{0})", typedef.Declaration.QualifiedOriginalName); } diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index a6281968..6182d191 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -970,7 +970,7 @@ namespace CppSharp.Generators.CLI if (Driver.Options.MarshalCharAsManagedChar) { foreach (var param in method.Parameters.Where( - p => p.Type.Desugar().IsPrimitiveType(PrimitiveType.Int8))) + p => p.Type.IsPrimitiveType(PrimitiveType.Int8))) { WriteLine("if ({0} < System::Char::MinValue || {0} > System::SByte::MaxValue)", param.Name); WriteLineIndent( diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index c5aaebc4..52e2fe6c 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -2105,7 +2105,7 @@ namespace CppSharp.Generators.CSharp if (Driver.Options.MarshalCharAsManagedChar) { foreach (var param in method.Parameters.Where( - p => p.Type.Desugar().IsPrimitiveType(PrimitiveType.Int8))) + p => p.Type.IsPrimitiveType(PrimitiveType.Int8))) { WriteLine("if ({0} < char.MinValue || {0} > sbyte.MaxValue)", param.Name); WriteLineIndent( @@ -2690,7 +2690,7 @@ namespace CppSharp.Generators.CSharp WriteLineIndent("EntryPoint=\"{0}\")]", function.Mangled); - if (function.ReturnType.Type.Desugar().IsPrimitiveType(PrimitiveType.Bool)) + if (function.ReturnType.Type.IsPrimitiveType(PrimitiveType.Bool)) WriteLine("[return: MarshalAsAttribute(UnmanagedType.I1)]"); var @params = new List(); diff --git a/src/Generator/Passes/CheckIgnoredDecls.cs b/src/Generator/Passes/CheckIgnoredDecls.cs index fc90c237..1d200420 100644 --- a/src/Generator/Passes/CheckIgnoredDecls.cs +++ b/src/Generator/Passes/CheckIgnoredDecls.cs @@ -342,7 +342,7 @@ namespace CppSharp.Passes var arrayType = type as ArrayType; PrimitiveType primitive; if (arrayType != null && arrayType.SizeType == ArrayType.ArraySize.Constant && - !arrayType.Type.Desugar().IsPrimitiveType(out primitive) && + !arrayType.Type.IsPrimitiveType(out primitive) && !arrayType.Type.Desugar().IsPointerToPrimitiveType()) { msg = "unsupported"; From 92568fadbfadd9d03f679c73c00b757648bf2f59 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Wed, 16 Apr 2014 19:59:51 +0200 Subject: [PATCH 7/9] Added new extension method Type.GetPointee() which returns the pointee of either a Pointer- or MemberPointerType. --- src/AST/TypeExtensions.cs | 45 ++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/AST/TypeExtensions.cs b/src/AST/TypeExtensions.cs index 837c47f7..6636d880 100644 --- a/src/AST/TypeExtensions.cs +++ b/src/AST/TypeExtensions.cs @@ -156,32 +156,37 @@ return t; } - public static Type GetFinalPointee(this PointerType pointer) + /// + /// If t is a pointer type the type pointed to by t will be returned. + /// Otherwise null. + /// + public static Type GetPointee(this Type t) { - var pointee = pointer.Pointee; - while (pointee.IsPointer()) - { - var p = pointee as PointerType; - if (p != null) - pointee = p.Pointee; - else - return GetFinalPointee(pointee as MemberPointerType); - } - return pointee; + var ptr = t as PointerType; + if (ptr != null) + return ptr.Pointee; + var memberPtr = t as MemberPointerType; + if (memberPtr != null) + return memberPtr.Pointee; + return null; } - public static Type GetFinalPointee(this MemberPointerType pointer) + /// + /// If t is a pointer type the type pointed to by t will be returned + /// after fully dereferencing it. Otherwise null. + /// For example int** -> int. + /// + public static Type GetFinalPointee(this Type t) { - var pointee = pointer.Pointee; - while (pointee.IsPointer()) + var finalPointee = t.GetPointee(); + var pointee = finalPointee; + while (pointee != null) { - var p = pointee as MemberPointerType; - if (p != null) - pointee = p.Pointee; - else - return GetFinalPointee(pointee as PointerType); + pointee = pointee.GetPointee(); + if (pointee != null) + finalPointee = pointee; } - return pointee; + return finalPointee; } } } \ No newline at end of file From 15f1394aaf1c3b15ea122da4cfd2031b7e40e302 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Wed, 16 Apr 2014 20:03:48 +0200 Subject: [PATCH 8/9] The extension method Type.IsPointerTo will take attributed types into account. Fixed generation of attributed delegate types in my case. --- src/AST/TypeExtensions.cs | 33 +++++++++++++-------------------- tests/Basic/Basic.Tests.cs | 8 ++++++++ tests/Basic/Basic.h | 8 ++++++++ 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/AST/TypeExtensions.cs b/src/AST/TypeExtensions.cs index 6636d880..ebbfe5de 100644 --- a/src/AST/TypeExtensions.cs +++ b/src/AST/TypeExtensions.cs @@ -90,26 +90,19 @@ if (ptr == null) return false; return ptr.Pointee.IsPrimitiveType(primitive); - } - - public static bool IsPointerTo(this Type t, out T type) where T : Type - { - var ptr = t as PointerType; - - if (ptr == null) - { - var functionPointer = t as MemberPointerType; - if (functionPointer != null) - { - type = functionPointer.Pointee as T; - return type != null; - } - type = null; - return false; - } - - type = ptr.Pointee as T; - return type != null; + } + + public static bool IsPointerTo(this Type t, out T type) where T : Type + { + var pointee = t.GetPointee(); + type = pointee as T; + if (type == null) + { + var attributedType = pointee as AttributedType; + if (attributedType != null) + type = attributedType.Modified.Type as T; + } + return type != null; } public static bool IsTagDecl(this Type t, out T decl) where T : Declaration diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index fc289418..c79f4079 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -176,6 +176,14 @@ public class BasicTests : GeneratorTestFixture var delegates = new TestDelegates(); var doubleSum = delegates.A(2) + delegates.B(2); Assert.AreEqual(8, doubleSum); + } + + [Test] + public void TestAttributedDelegate() + { + var attributedDelegate = basic.GetAttributedDelegate(); + var result = attributedDelegate(2); + Assert.AreEqual(4, result); } [Test] diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 29012b47..d8550963 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -259,6 +259,14 @@ struct DLL_API TestDelegates MemberDelegate C; }; +// Tests delegate generation for attributed function types +typedef int(__cdecl *AttributedDelegate)(int n); +DLL_API int __cdecl Double(int n) { return n * 2; } +DLL_API AttributedDelegate GetAttributedDelegate() +{ + return Double; +} + // Tests memory leaks in constructors // C#: Marshal.FreeHGlobal(arg0); struct DLL_API TestMemoryLeaks From 325bca608297d2c441011178024d89c1c1e54b39 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Wed, 16 Apr 2014 20:28:23 +0200 Subject: [PATCH 9/9] CLI generator didn't respect static properties. --- src/Generator/Generators/CLI/CLIHeadersTemplate.cs | 5 ++++- tests/Basic/Basic.Tests.cs | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs index ef1c6adb..4b49a012 100644 --- a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs +++ b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs @@ -638,7 +638,10 @@ namespace CppSharp.Generators.CLI return; PushBlock(CLIBlockKind.Property, property); - var type = property.QualifiedType.Visit(TypePrinter); + var type = property.QualifiedType.Visit(TypePrinter); + + if (property.IsStatic) + Write("static "); if (property.IsIndexer) { diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index bc327f6b..68f4eaf6 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -181,8 +181,7 @@ public class BasicTests : GeneratorTestFixture [Test] public void TestAttributedDelegate() { - var attributedDelegate = basic.GetAttributedDelegate(); - var result = attributedDelegate(2); + var result = basic.AttributedDelegate(2); Assert.AreEqual(4, result); }