mirror of https://github.com/mono/CppSharp.git
c-sharpdotnetmonobindingsbridgecclangcpluspluscppsharpglueinteropparserparsingpinvokeswigsyntax-treevisitorsxamarinxamarin-bindings
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
5.7 KiB
197 lines
5.7 KiB
using System; |
|
using System.IO; |
|
using System.Linq; |
|
using System.Collections.Generic; |
|
using System.Reflection; |
|
|
|
using System.CodeDom; |
|
using Mono.VisualC.Interop; |
|
using Mono.VisualC.Code; |
|
|
|
namespace Mono.VisualC.Code.Atoms { |
|
|
|
public class Class : CodeContainer { |
|
|
|
// FIXME: This should be moved into Mono.VisualC.Interop and an attribute |
|
// for name mangling purposes (MSVC mangles differently depending on defined as class or struct). |
|
public enum Definition { |
|
Class, |
|
Struct |
|
} |
|
public struct BaseClass { |
|
public string Name; |
|
public Access Access; |
|
public bool IsVirtual; |
|
} |
|
|
|
public string Name { get; set; } |
|
public string StaticCppLibrary { get; set; } |
|
public Definition DefinedAs { get; set; } |
|
|
|
public IList<BaseClass> Bases { get; set; } |
|
public IList<string> TemplateArguments { get; set; } |
|
|
|
public Class (string name) |
|
{ |
|
Name = name; |
|
Bases = new List<BaseClass> (); |
|
TemplateArguments = new List<string> (); |
|
} |
|
|
|
internal protected override object InsideCodeNamespace (CodeNamespace ns) |
|
{ |
|
var wrapper = CreateWrapperClass (); |
|
ns.Types.Add (wrapper); |
|
return wrapper; |
|
} |
|
|
|
private CodeTypeDeclaration CreateWrapperClass () |
|
{ |
|
var wrapper = new CodeTypeDeclaration (Name) { TypeAttributes = TypeAttributes.Public }; |
|
foreach (var arg in TemplateArguments) |
|
wrapper.TypeParameters.Add (arg); |
|
|
|
var iface = CreateInterface (wrapper); |
|
wrapper.Members.Add (iface); |
|
|
|
var native = CreateNativeLayout (); |
|
wrapper.Members.Add (native); |
|
|
|
// FIXME: For now, we'll have the managed wrapper extend from the first public base class |
|
string managedBase = Bases.Where (b => b.Access == Access.Public).Select (b => b.Name).FirstOrDefault (); |
|
bool hasOverrides = true; |
|
|
|
if (managedBase == null) { |
|
managedBase = typeof (ICppObject).Name; |
|
hasOverrides = false; |
|
|
|
// Add Native property |
|
var nativeField = new CodeMemberField (typeof (CppInstancePtr).Name, "native_ptr") { Attributes = MemberAttributes.Family }; |
|
var nativeProperty = new CodeMemberProperty { |
|
Name = "Native", |
|
Type = new CodeTypeReference (typeof (CppInstancePtr).Name), |
|
HasSet = false, |
|
Attributes = MemberAttributes.Public | MemberAttributes.Final |
|
}; |
|
nativeProperty.GetStatements.Add (new CodeMethodReturnStatement (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), nativeField.Name))); |
|
|
|
wrapper.Members.Add (nativeField); |
|
wrapper.Members.Add (nativeProperty); |
|
} |
|
wrapper.BaseTypes.Add (managedBase); |
|
|
|
// add static impl field |
|
var implField = new CodeMemberField (iface.TypeReference (), "impl") { Attributes = MemberAttributes.Static | MemberAttributes.Private }; |
|
if (StaticCppLibrary != null) { |
|
CodeTypeReference [] types = new CodeTypeReference [] { |
|
iface.TypeReference (), |
|
native.TypeReference (), |
|
wrapper.TypeReference () |
|
}; |
|
var getClassMethod = new CodeMethodReferenceExpression (new CodeTypeReferenceExpression (StaticCppLibrary), "GetClass", types); |
|
implField.InitExpression = new CodeMethodInvokeExpression (getClassMethod, new CodePrimitiveExpression (Name)); |
|
} |
|
wrapper.Members.Add (implField); |
|
|
|
CodeMemberMethod dispose = null; |
|
foreach (var atom in Atoms) { |
|
Method method = atom as Method; |
|
if (method != null && method.IsDestructor) |
|
dispose = (CodeMemberMethod)method.InsideCodeTypeDeclaration (wrapper); |
|
else |
|
atom.Visit (wrapper); |
|
} |
|
|
|
if (dispose == null) |
|
wrapper.Members.Add (CreateDestructorlessDispose ()); |
|
else if (hasOverrides) |
|
dispose.Attributes |= MemberAttributes.Override; |
|
|
|
return wrapper; |
|
} |
|
|
|
private CodeTypeDeclaration CreateInterface (CodeTypeDeclaration wrapper) |
|
{ |
|
var iface = new CodeTypeDeclaration ("I" + Name) { |
|
TypeAttributes = TypeAttributes.Interface | TypeAttributes.NestedPublic, |
|
Attributes = MemberAttributes.Public, |
|
IsInterface = true |
|
}; |
|
|
|
foreach (var arg in TemplateArguments) |
|
iface.TypeParameters.Add (arg); |
|
|
|
iface.BaseTypes.Add (new CodeTypeReference (typeof (ICppClassOverridable<>).Name, wrapper.TypeReference ())); |
|
|
|
foreach (var atom in Atoms) |
|
atom.Visit (iface); |
|
|
|
return iface; |
|
} |
|
|
|
private CodeTypeDeclaration CreateNativeLayout () |
|
{ |
|
var native = new CodeTypeDeclaration ("_" + Name) { |
|
TypeAttributes = TypeAttributes.NestedPrivate | TypeAttributes.SequentialLayout, |
|
Attributes = MemberAttributes.Private, |
|
IsStruct = true |
|
}; |
|
|
|
foreach (var atom in Atoms) |
|
atom.Visit (native); |
|
|
|
return native; |
|
} |
|
|
|
private CodeMemberMethod CreateDestructorlessDispose () |
|
{ |
|
var dispose = new CodeMemberMethod { |
|
Name = "Dispose", |
|
Attributes = MemberAttributes.Public |
|
}; |
|
|
|
var warning = new CodeCommentStatement ("FIXME: Check for inline destructor for this class."); |
|
dispose.Statements.Add (warning); |
|
|
|
var native = new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), "Native"); |
|
dispose.Statements.Add (new CodeMethodInvokeExpression (native, "Dispose")); |
|
|
|
return dispose; |
|
} |
|
|
|
public override void Write (TextWriter writer) |
|
{ |
|
string declarator = (DefinedAs == Definition.Class? "class" : "struct"); |
|
writer.Write ("{0} {1}", declarator, Name); |
|
|
|
var bce = Bases.GetEnumerator (); |
|
|
|
if (bce.MoveNext ()) { |
|
writer.Write (" : "); |
|
|
|
while (true) { |
|
var baseClass = bce.Current; |
|
|
|
if (baseClass.IsVirtual) writer.Write ("virtual "); |
|
switch (baseClass.Access) { |
|
case Access.Public: writer.Write ("public "); break; |
|
case Access.Protected: writer.Write ("protected "); break; |
|
case Access.Private: writer.Write ("private "); break; |
|
} |
|
|
|
writer.Write (baseClass.Name); |
|
|
|
if (!bce.MoveNext ()) |
|
break; |
|
|
|
writer.Write (", "); |
|
} |
|
} |
|
|
|
writer.WriteLine (" {"); |
|
base.Write (writer); |
|
writer.WriteLine ("};"); |
|
} |
|
} |
|
} |
|
|
|
|