From 4cfcfa1b164bf2864f052592ba28caebe612036b Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Sun, 1 Sep 2013 15:03:16 +0300 Subject: [PATCH] Corrected the implementation of abstract methods to properly handle classes, instance arguments and indirect return types. Signed-off-by: Dimitar Dobrev --- .../Generators/CSharp/CSharpTextTemplate.cs | 15 +++++----- .../Passes/AbstractImplementationsPass.cs | 28 +++++++++++++++---- tests/Basic/Basic.Tests.cs | 2 +- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index e2284d4d..abd433fa 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -1528,7 +1528,7 @@ namespace CppSharp.Generators.CSharp } else if (method.IsOverride && method.IsSynthetized) { - GenerateVirtualTableMethodCall(method, @class); + GenerateVirtualTableFunctionCall(method, @class); } else { @@ -1557,7 +1557,7 @@ namespace CppSharp.Generators.CSharp PopBlock(NewLineKind.BeforeNextBlock); } - private void GenerateVirtualTableMethodCall(Method method, Class @class) + private void GenerateVirtualTableFunctionCall(Method method, Class @class) { WriteLine("void* vtable = *((void**) __Instance.ToPointer());"); int i; @@ -1573,15 +1573,12 @@ namespace CppSharp.Generators.CSharp i = @class.Layout.Layout.Components.FindIndex(m => m.Method == method); break; } - WriteLine("void* slot = *((void**) vtable + {0} * sizeof(IntPtr));", i); + WriteLine("void* slot = *((void**) vtable + {0} * IntPtr.Size);", i); string @delegate = method.Name + "Delegate"; string delegateId = GeneratedIdentifier(@delegate); - WriteLine("{0} {1} = ({0}) Marshal.GetDelegateForFunctionPointer(new IntPtr(slot), typeof({0}));", + WriteLine("var {1} = ({0}) Marshal.GetDelegateForFunctionPointer(new IntPtr(slot), typeof({0}));", @delegate, delegateId); - if (!method.OriginalReturnType.Type.IsPrimitiveType(PrimitiveType.Void)) - Write("return "); - WriteLine("{0}({1});", delegateId, string.Join(", ", method.Parameters.Where( - p => p.Kind != ParameterKind.IndirectReturnType).Select(p => Helpers.SafeIdentifier(p.Name)))); + GenerateFunctionCall(delegateId, method.Parameters, method); } private void GenerateOperator(Method method, Class @class) @@ -1937,9 +1934,11 @@ namespace CppSharp.Generators.CSharp PushBlock(CSharpBlockKind.Typedef); WriteLine("[UnmanagedFunctionPointerAttribute(CallingConvention.{0})]", Helpers.ToCSharpCallConv(functionType.CallingConvention)); + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); WriteLine("public {0};", string.Format(TypePrinter.VisitDelegate(functionType).Type, SafeIdentifier(typedef.Name))); + TypePrinter.PopContext(); PopBlock(NewLineKind.BeforeNextBlock); } else if (typedef.Type.IsEnumType()) diff --git a/src/Generator/Passes/AbstractImplementationsPass.cs b/src/Generator/Passes/AbstractImplementationsPass.cs index af8562f1..4321a892 100644 --- a/src/Generator/Passes/AbstractImplementationsPass.cs +++ b/src/Generator/Passes/AbstractImplementationsPass.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using CppSharp.AST; using CppSharp.Utils; @@ -57,12 +56,29 @@ namespace CppSharp.Passes { internalImplementation.Methods.Add(new Method(abstractMethod)); var @delegate = new TypedefDecl { Name = abstractMethod.Name + "Delegate" }; - var pointerType = new PointerType(); var functionType = new FunctionType(); functionType.CallingConvention = abstractMethod.CallingConvention; - functionType.ReturnType = abstractMethod.OriginalReturnType; - functionType.Parameters.AddRange(abstractMethod.Parameters.Where( - p => p.Kind != ParameterKind.IndirectReturnType)); + functionType.ReturnType = abstractMethod.ReturnType; + var instance = new Parameter(); + instance.Name = "instance"; + instance.QualifiedType = new QualifiedType(new BuiltinType(PrimitiveType.IntPtr)); + functionType.Parameters.Add(instance); + functionType.Parameters.AddRange(abstractMethod.Parameters); + for (int i = functionType.Parameters.Count - 1; i >= 0; i--) + { + var parameter = functionType.Parameters[i]; + if (parameter.Kind == ParameterKind.IndirectReturnType) + { + var retParam = new Parameter(); + retParam.Name = parameter.Name; + var ptrType = new PointerType(); + ptrType.QualifiedPointee = new QualifiedType(parameter.Type); + retParam.QualifiedType = new QualifiedType(ptrType); + functionType.Parameters.RemoveAt(i); + functionType.Parameters.Insert(i, retParam); + } + } + var pointerType = new PointerType(); pointerType.QualifiedPointee = new QualifiedType(functionType); @delegate.QualifiedType = new QualifiedType(pointerType); @delegate.IgnoreFlags = abstractMethod.IgnoreFlags; diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index 68992b2c..70a13733 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -90,7 +90,7 @@ public class BasicTests public void TestAbstractReturnType() { var returnsAbstractFoo = new ReturnsAbstractFoo(); - AbstractFoo abstractFoo = returnsAbstractFoo.getFoo(); + var abstractFoo = returnsAbstractFoo.getFoo(); Assert.AreEqual(abstractFoo.pureFunction(), 5); } }