diff --git a/src/AST/Function.cs b/src/AST/Function.cs
index a9043167..04a20a0a 100644
--- a/src/AST/Function.cs
+++ b/src/AST/Function.cs
@@ -165,27 +165,30 @@ namespace CppSharp.AST
public virtual QualifiedType GetFunctionType()
{
- var functionType = new FunctionType();
- functionType.CallingConvention = CallingConvention;
- functionType.ReturnType = ReturnType;
+ var functionType = new FunctionType
+ {
+ CallingConvention = this.CallingConvention,
+ ReturnType = this.ReturnType
+ };
functionType.Parameters.AddRange(Parameters);
+ ReplaceIndirectReturnParamWithRegular(functionType);
+ var pointerType = new PointerType { QualifiedPointee = new QualifiedType(functionType) };
+ return new QualifiedType(pointerType);
+ }
+
+ private static void ReplaceIndirectReturnParamWithRegular(FunctionType functionType)
+ {
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);
+ var ptrType = new PointerType { QualifiedPointee = new QualifiedType(parameter.Type) };
+ var retParam = new Parameter { Name = parameter.Name, QualifiedType = new QualifiedType(ptrType) };
functionType.Parameters.RemoveAt(i);
functionType.Parameters.Insert(i, retParam);
}
}
- var pointerType = new PointerType();
- pointerType.QualifiedPointee = new QualifiedType(functionType);
- return new QualifiedType(pointerType);
}
}
}
\ No newline at end of file
diff --git a/src/AST/Method.cs b/src/AST/Method.cs
index 9a21f371..74285471 100644
--- a/src/AST/Method.cs
+++ b/src/AST/Method.cs
@@ -127,10 +127,11 @@ namespace CppSharp.AST
{
FunctionType functionType;
qualifiedType.Type.IsPointerTo(out functionType);
- var instance = new Parameter();
- instance.Name = "instance";
- instance.QualifiedType = new QualifiedType(
- new BuiltinType(PrimitiveType.IntPtr));
+ var instance = new Parameter
+ {
+ Name = "instance",
+ QualifiedType = new QualifiedType(new BuiltinType(PrimitiveType.IntPtr))
+ };
functionType.Parameters.Insert(0, instance);
}
return qualifiedType;
diff --git a/src/Generator/AST/VTables.cs b/src/Generator/AST/VTables.cs
index d3894996..edd24d44 100644
--- a/src/Generator/AST/VTables.cs
+++ b/src/Generator/AST/VTables.cs
@@ -83,41 +83,18 @@ namespace CppSharp.AST
throw new NotSupportedException();
}
- public static string GetVirtualCallDelegate(INamedDecl method, Class @class,
- bool is32Bit, out string delegateId)
+ public static int GetVTableIndex(INamedDecl method, Class @class)
{
- var virtualCallBuilder = new StringBuilder();
- virtualCallBuilder.AppendFormat(
- "void* vtable = *((void**) {0}.ToPointer());",
- Helpers.InstanceIdentifier);
- virtualCallBuilder.AppendLine();
-
- int i;
switch (@class.Layout.ABI)
{
case CppAbi.Microsoft:
- i = (from table in @class.Layout.VFTables
- let j = table.Layout.Components.FindIndex(m => m.Method == method)
- where j >= 0
- select j).First();
- break;
+ return (from table in @class.Layout.VFTables
+ let j = table.Layout.Components.FindIndex(m => m.Method == method)
+ where j >= 0
+ select j).First();
default:
- i = @class.Layout.Layout.Components.FindIndex(m => m.Method == method);
- break;
+ return @class.Layout.Layout.Components.FindIndex(m => m.Method == method);
}
-
- virtualCallBuilder.AppendFormat(
- "void* slot = *((void**) vtable + {0} * {1});", i, is32Bit ? 4 : 8);
- virtualCallBuilder.AppendLine();
-
- string @delegate = method.Name + "Delegate";
- delegateId = Generator.GeneratedIdentifier(@delegate);
-
- virtualCallBuilder.AppendFormat(
- "var {1} = ({0}) Marshal.GetDelegateForFunctionPointer(new IntPtr(slot), typeof({0}));",
- @delegate, delegateId);
- virtualCallBuilder.AppendLine();
- return virtualCallBuilder.ToString();
}
}
}
diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs
index cfa1821f..83c11c47 100644
--- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs
+++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs
@@ -626,8 +626,7 @@ namespace CppSharp.Generators.CSharp
Write(Helpers.GetAccess(@class));
Write("unsafe ");
- if (Driver.Options.GenerateAbstractImpls &&
- @class.IsAbstract)
+ if (Driver.Options.GenerateAbstractImpls && @class.IsAbstract)
Write("abstract ");
if (Options.GeneratePartialClasses)
@@ -1365,8 +1364,7 @@ namespace CppSharp.Generators.CSharp
PushBlock(CSharpBlockKind.Method);
string className = @class.Name;
string safeIdentifier = SafeIdentifier(className);
- if (@class.Access == AccessSpecifier.Private &&
- className.EndsWith("Internal"))
+ if (@class.Access == AccessSpecifier.Private && className.EndsWith("Internal"))
{
className = className.Substring(0,
safeIdentifier.LastIndexOf("Internal", StringComparison.Ordinal));
@@ -1379,8 +1377,7 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock);
PushBlock(CSharpBlockKind.Method);
- WriteLine("internal {0}({1}.Internal native)", safeIdentifier,
- className);
+ WriteLine("internal {0}({1}.Internal native)", safeIdentifier, className);
WriteLineIndent(": this(&native)");
WriteStartBraceIndent();
WriteCloseBraceIndent();
@@ -1574,10 +1571,34 @@ namespace CppSharp.Generators.CSharp
private void GenerateVirtualTableFunctionCall(Function method, Class @class)
{
string delegateId;
- Write(VTables.GetVirtualCallDelegate(method, @class, Driver.Options.Is32Bit, out delegateId));
+ Write(GetVirtualCallDelegate(method, @class, Driver.Options.Is32Bit, out delegateId));
GenerateFunctionCall(delegateId, method.Parameters, method);
}
+ public static string GetVirtualCallDelegate(INamedDecl method, Class @class,
+ bool is32Bit, out string delegateId)
+ {
+ var virtualCallBuilder = new StringBuilder();
+ virtualCallBuilder.AppendFormat("void* vtable = *((void**) {0}.ToPointer());",
+ Helpers.InstanceIdentifier);
+ virtualCallBuilder.AppendLine();
+
+ var i = VTables.GetVTableIndex(method, @class);
+
+ virtualCallBuilder.AppendFormat(
+ "void* slot = *((void**) vtable + {0} * {1});", i, is32Bit ? 4 : 8);
+ virtualCallBuilder.AppendLine();
+
+ string @delegate = method.Name + "Delegate";
+ delegateId = Generator.GeneratedIdentifier(@delegate);
+
+ virtualCallBuilder.AppendFormat(
+ "var {1} = ({0}) Marshal.GetDelegateForFunctionPointer(new IntPtr(slot), typeof({0}));",
+ @delegate, delegateId);
+ virtualCallBuilder.AppendLine();
+ return virtualCallBuilder.ToString();
+ }
+
private void GenerateOperator(Method method, Class @class)
{
if (method.IsSynthetized)
diff --git a/src/Generator/Passes/GenerateAbstractImplementationsPass.cs b/src/Generator/Passes/GenerateAbstractImplementationsPass.cs
index ee8c1e1f..951650c1 100644
--- a/src/Generator/Passes/GenerateAbstractImplementationsPass.cs
+++ b/src/Generator/Passes/GenerateAbstractImplementationsPass.cs
@@ -5,6 +5,11 @@ using CppSharp.Utils;
namespace CppSharp.Passes
{
+ ///
+ /// This pass generates internal classes that implement abstract classes.
+ /// When the return type of a function is abstract, these internal classes provide -
+ /// since the real type cannot be resolved while binding - an allocatable class that supports proper polymorphism.
+ ///
public class GenerateAbstractImplementationsPass : TranslationUnitPass
{
private readonly List classes = new List();
@@ -39,9 +44,12 @@ namespace CppSharp.Passes
foreach (var abstractMethod in abstractMethods)
{
internalImpl.Methods.Add(new Method(abstractMethod));
- var @delegate = new TypedefDecl { Name = abstractMethod.Name + "Delegate" };
- @delegate.QualifiedType = abstractMethod.GetFunctionType();
- @delegate.IgnoreFlags = abstractMethod.IgnoreFlags;
+ var @delegate = new TypedefDecl
+ {
+ Name = abstractMethod.Name + "Delegate",
+ QualifiedType = abstractMethod.GetFunctionType(),
+ IgnoreFlags = abstractMethod.IgnoreFlags
+ };
internalImpl.Typedefs.Add(@delegate);
}
@@ -59,10 +67,12 @@ namespace CppSharp.Passes
private static Class GetInternalImpl(Declaration @class)
{
- var internalImpl = new Class();
- internalImpl.Name = @class.Name + "Internal";
- internalImpl.Access = AccessSpecifier.Private;
- internalImpl.Namespace = @class.Namespace;
+ var internalImpl = new Class
+ {
+ Name = @class.Name + "Internal",
+ Access = AccessSpecifier.Private,
+ Namespace = @class.Namespace
+ };
var @base = new BaseClassSpecifier { Type = new TagType(@class) };
internalImpl.Bases.Add(@base);
return internalImpl;