Browse Source

Commented the pass about internal impls of abstract classes. Cosmetic fixes.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/53/head
Dimitar Dobrev 13 years ago
parent
commit
1c793ef589
  1. 25
      src/AST/Function.cs
  2. 9
      src/AST/Method.cs
  3. 35
      src/Generator/AST/VTables.cs
  4. 35
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  5. 24
      src/Generator/Passes/GenerateAbstractImplementationsPass.cs

25
src/AST/Function.cs

@ -165,27 +165,30 @@ namespace CppSharp.AST
public virtual QualifiedType GetFunctionType() public virtual QualifiedType GetFunctionType()
{ {
var functionType = new FunctionType(); var functionType = new FunctionType
functionType.CallingConvention = CallingConvention; {
functionType.ReturnType = ReturnType; CallingConvention = this.CallingConvention,
ReturnType = this.ReturnType
};
functionType.Parameters.AddRange(Parameters); 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--) for (int i = functionType.Parameters.Count - 1; i >= 0; i--)
{ {
var parameter = functionType.Parameters[i]; var parameter = functionType.Parameters[i];
if (parameter.Kind == ParameterKind.IndirectReturnType) if (parameter.Kind == ParameterKind.IndirectReturnType)
{ {
var retParam = new Parameter(); var ptrType = new PointerType { QualifiedPointee = new QualifiedType(parameter.Type) };
retParam.Name = parameter.Name; var retParam = new Parameter { Name = parameter.Name, QualifiedType = new QualifiedType(ptrType) };
var ptrType = new PointerType();
ptrType.QualifiedPointee = new QualifiedType(parameter.Type);
retParam.QualifiedType = new QualifiedType(ptrType);
functionType.Parameters.RemoveAt(i); functionType.Parameters.RemoveAt(i);
functionType.Parameters.Insert(i, retParam); functionType.Parameters.Insert(i, retParam);
} }
} }
var pointerType = new PointerType();
pointerType.QualifiedPointee = new QualifiedType(functionType);
return new QualifiedType(pointerType);
} }
} }
} }

9
src/AST/Method.cs

@ -127,10 +127,11 @@ namespace CppSharp.AST
{ {
FunctionType functionType; FunctionType functionType;
qualifiedType.Type.IsPointerTo(out functionType); qualifiedType.Type.IsPointerTo(out functionType);
var instance = new Parameter(); var instance = new Parameter
instance.Name = "instance"; {
instance.QualifiedType = new QualifiedType( Name = "instance",
new BuiltinType(PrimitiveType.IntPtr)); QualifiedType = new QualifiedType(new BuiltinType(PrimitiveType.IntPtr))
};
functionType.Parameters.Insert(0, instance); functionType.Parameters.Insert(0, instance);
} }
return qualifiedType; return qualifiedType;

35
src/Generator/AST/VTables.cs

@ -83,41 +83,18 @@ namespace CppSharp.AST
throw new NotSupportedException(); throw new NotSupportedException();
} }
public static string GetVirtualCallDelegate(INamedDecl method, Class @class, public static int GetVTableIndex(INamedDecl method, Class @class)
bool is32Bit, out string delegateId)
{ {
var virtualCallBuilder = new StringBuilder();
virtualCallBuilder.AppendFormat(
"void* vtable = *((void**) {0}.ToPointer());",
Helpers.InstanceIdentifier);
virtualCallBuilder.AppendLine();
int i;
switch (@class.Layout.ABI) switch (@class.Layout.ABI)
{ {
case CppAbi.Microsoft: case CppAbi.Microsoft:
i = (from table in @class.Layout.VFTables return (from table in @class.Layout.VFTables
let j = table.Layout.Components.FindIndex(m => m.Method == method) let j = table.Layout.Components.FindIndex(m => m.Method == method)
where j >= 0 where j >= 0
select j).First(); select j).First();
break;
default: default:
i = @class.Layout.Layout.Components.FindIndex(m => m.Method == method); return @class.Layout.Layout.Components.FindIndex(m => m.Method == method);
break;
} }
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();
} }
} }
} }

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

@ -626,8 +626,7 @@ namespace CppSharp.Generators.CSharp
Write(Helpers.GetAccess(@class)); Write(Helpers.GetAccess(@class));
Write("unsafe "); Write("unsafe ");
if (Driver.Options.GenerateAbstractImpls && if (Driver.Options.GenerateAbstractImpls && @class.IsAbstract)
@class.IsAbstract)
Write("abstract "); Write("abstract ");
if (Options.GeneratePartialClasses) if (Options.GeneratePartialClasses)
@ -1365,8 +1364,7 @@ namespace CppSharp.Generators.CSharp
PushBlock(CSharpBlockKind.Method); PushBlock(CSharpBlockKind.Method);
string className = @class.Name; string className = @class.Name;
string safeIdentifier = SafeIdentifier(className); string safeIdentifier = SafeIdentifier(className);
if (@class.Access == AccessSpecifier.Private && if (@class.Access == AccessSpecifier.Private && className.EndsWith("Internal"))
className.EndsWith("Internal"))
{ {
className = className.Substring(0, className = className.Substring(0,
safeIdentifier.LastIndexOf("Internal", StringComparison.Ordinal)); safeIdentifier.LastIndexOf("Internal", StringComparison.Ordinal));
@ -1379,8 +1377,7 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
PushBlock(CSharpBlockKind.Method); PushBlock(CSharpBlockKind.Method);
WriteLine("internal {0}({1}.Internal native)", safeIdentifier, WriteLine("internal {0}({1}.Internal native)", safeIdentifier, className);
className);
WriteLineIndent(": this(&native)"); WriteLineIndent(": this(&native)");
WriteStartBraceIndent(); WriteStartBraceIndent();
WriteCloseBraceIndent(); WriteCloseBraceIndent();
@ -1574,10 +1571,34 @@ namespace CppSharp.Generators.CSharp
private void GenerateVirtualTableFunctionCall(Function method, Class @class) private void GenerateVirtualTableFunctionCall(Function method, Class @class)
{ {
string delegateId; 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); 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) private void GenerateOperator(Method method, Class @class)
{ {
if (method.IsSynthetized) if (method.IsSynthetized)

24
src/Generator/Passes/GenerateAbstractImplementationsPass.cs

@ -5,6 +5,11 @@ using CppSharp.Utils;
namespace CppSharp.Passes namespace CppSharp.Passes
{ {
/// <summary>
/// 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.
/// </summary>
public class GenerateAbstractImplementationsPass : TranslationUnitPass public class GenerateAbstractImplementationsPass : TranslationUnitPass
{ {
private readonly List<Class> classes = new List<Class>(); private readonly List<Class> classes = new List<Class>();
@ -39,9 +44,12 @@ namespace CppSharp.Passes
foreach (var abstractMethod in abstractMethods) foreach (var abstractMethod in abstractMethods)
{ {
internalImpl.Methods.Add(new Method(abstractMethod)); internalImpl.Methods.Add(new Method(abstractMethod));
var @delegate = new TypedefDecl { Name = abstractMethod.Name + "Delegate" }; var @delegate = new TypedefDecl
@delegate.QualifiedType = abstractMethod.GetFunctionType(); {
@delegate.IgnoreFlags = abstractMethod.IgnoreFlags; Name = abstractMethod.Name + "Delegate",
QualifiedType = abstractMethod.GetFunctionType(),
IgnoreFlags = abstractMethod.IgnoreFlags
};
internalImpl.Typedefs.Add(@delegate); internalImpl.Typedefs.Add(@delegate);
} }
@ -59,10 +67,12 @@ namespace CppSharp.Passes
private static Class GetInternalImpl(Declaration @class) private static Class GetInternalImpl(Declaration @class)
{ {
var internalImpl = new Class(); var internalImpl = new Class
internalImpl.Name = @class.Name + "Internal"; {
internalImpl.Access = AccessSpecifier.Private; Name = @class.Name + "Internal",
internalImpl.Namespace = @class.Namespace; Access = AccessSpecifier.Private,
Namespace = @class.Namespace
};
var @base = new BaseClassSpecifier { Type = new TagType(@class) }; var @base = new BaseClassSpecifier { Type = new TagType(@class) };
internalImpl.Bases.Add(@base); internalImpl.Bases.Add(@base);
return internalImpl; return internalImpl;

Loading…
Cancel
Save