Browse Source

Corrected the implementation of abstract methods to properly handle classes, instance arguments and indirect return types.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/53/head
Dimitar Dobrev 13 years ago
parent
commit
4cfcfa1b16
  1. 15
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  2. 28
      src/Generator/Passes/AbstractImplementationsPass.cs
  3. 2
      tests/Basic/Basic.Tests.cs

15
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -1528,7 +1528,7 @@ namespace CppSharp.Generators.CSharp
} }
else if (method.IsOverride && method.IsSynthetized) else if (method.IsOverride && method.IsSynthetized)
{ {
GenerateVirtualTableMethodCall(method, @class); GenerateVirtualTableFunctionCall(method, @class);
} }
else else
{ {
@ -1557,7 +1557,7 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }
private void GenerateVirtualTableMethodCall(Method method, Class @class) private void GenerateVirtualTableFunctionCall(Method method, Class @class)
{ {
WriteLine("void* vtable = *((void**) __Instance.ToPointer());"); WriteLine("void* vtable = *((void**) __Instance.ToPointer());");
int i; int i;
@ -1573,15 +1573,12 @@ namespace CppSharp.Generators.CSharp
i = @class.Layout.Layout.Components.FindIndex(m => m.Method == method); i = @class.Layout.Layout.Components.FindIndex(m => m.Method == method);
break; 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 @delegate = method.Name + "Delegate";
string delegateId = GeneratedIdentifier(@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); @delegate, delegateId);
if (!method.OriginalReturnType.Type.IsPrimitiveType(PrimitiveType.Void)) GenerateFunctionCall(delegateId, method.Parameters, method);
Write("return ");
WriteLine("{0}({1});", delegateId, string.Join(", ", method.Parameters.Where(
p => p.Kind != ParameterKind.IndirectReturnType).Select(p => Helpers.SafeIdentifier(p.Name))));
} }
private void GenerateOperator(Method method, Class @class) private void GenerateOperator(Method method, Class @class)
@ -1937,9 +1934,11 @@ namespace CppSharp.Generators.CSharp
PushBlock(CSharpBlockKind.Typedef); PushBlock(CSharpBlockKind.Typedef);
WriteLine("[UnmanagedFunctionPointerAttribute(CallingConvention.{0})]", WriteLine("[UnmanagedFunctionPointerAttribute(CallingConvention.{0})]",
Helpers.ToCSharpCallConv(functionType.CallingConvention)); Helpers.ToCSharpCallConv(functionType.CallingConvention));
TypePrinter.PushContext(CSharpTypePrinterContextKind.Native);
WriteLine("public {0};", WriteLine("public {0};",
string.Format(TypePrinter.VisitDelegate(functionType).Type, string.Format(TypePrinter.VisitDelegate(functionType).Type,
SafeIdentifier(typedef.Name))); SafeIdentifier(typedef.Name)));
TypePrinter.PopContext();
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }
else if (typedef.Type.IsEnumType()) else if (typedef.Type.IsEnumType())

28
src/Generator/Passes/AbstractImplementationsPass.cs

@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using CppSharp.AST; using CppSharp.AST;
using CppSharp.Utils; using CppSharp.Utils;
@ -57,12 +56,29 @@ namespace CppSharp.Passes
{ {
internalImplementation.Methods.Add(new Method(abstractMethod)); internalImplementation.Methods.Add(new Method(abstractMethod));
var @delegate = new TypedefDecl { Name = abstractMethod.Name + "Delegate" }; var @delegate = new TypedefDecl { Name = abstractMethod.Name + "Delegate" };
var pointerType = new PointerType();
var functionType = new FunctionType(); var functionType = new FunctionType();
functionType.CallingConvention = abstractMethod.CallingConvention; functionType.CallingConvention = abstractMethod.CallingConvention;
functionType.ReturnType = abstractMethod.OriginalReturnType; functionType.ReturnType = abstractMethod.ReturnType;
functionType.Parameters.AddRange(abstractMethod.Parameters.Where( var instance = new Parameter();
p => p.Kind != ParameterKind.IndirectReturnType)); 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); pointerType.QualifiedPointee = new QualifiedType(functionType);
@delegate.QualifiedType = new QualifiedType(pointerType); @delegate.QualifiedType = new QualifiedType(pointerType);
@delegate.IgnoreFlags = abstractMethod.IgnoreFlags; @delegate.IgnoreFlags = abstractMethod.IgnoreFlags;

2
tests/Basic/Basic.Tests.cs

@ -90,7 +90,7 @@ public class BasicTests
public void TestAbstractReturnType() public void TestAbstractReturnType()
{ {
var returnsAbstractFoo = new ReturnsAbstractFoo(); var returnsAbstractFoo = new ReturnsAbstractFoo();
AbstractFoo abstractFoo = returnsAbstractFoo.getFoo(); var abstractFoo = returnsAbstractFoo.getFoo();
Assert.AreEqual(abstractFoo.pureFunction(), 5); Assert.AreEqual(abstractFoo.pureFunction(), 5);
} }
} }

Loading…
Cancel
Save