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.
180 lines
7.1 KiB
180 lines
7.1 KiB
// |
|
// Class.cs: Represents a C++ class |
|
// |
|
// Author: |
|
// Alexander Corrado (alexander.corrado@gmail.com) |
|
// Andreia Gaita (shana@spoiledcat.net) |
|
// Zoltan Varga <vargaz@gmail.com> |
|
// |
|
// Copyright (C) 2011 Novell Inc. |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining |
|
// a copy of this software and associated documentation files (the |
|
// "Software"), to deal in the Software without restriction, including |
|
// without limitation the rights to use, copy, modify, merge, publish, |
|
// distribute, sublicense, and/or sell copies of the Software, and to |
|
// permit persons to whom the Software is furnished to do so, subject to |
|
// the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be |
|
// included in all copies or substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
|
|
using System; |
|
using System.Collections.Generic; |
|
using System.Reflection; |
|
using System.Linq; |
|
using System.CodeDom; |
|
using System.CodeDom.Compiler; |
|
|
|
class Class |
|
{ |
|
public Class (Node n) { |
|
Node = n; |
|
BaseClasses = new List<Class> (); |
|
Methods = new List<Method> (); |
|
Fields = new List<Field> (); |
|
Properties = new List<Property> (); |
|
} |
|
|
|
public Node Node { |
|
get; set; |
|
} |
|
|
|
public string Name { |
|
get { |
|
return Node.Name; |
|
} |
|
} |
|
|
|
public List<Class> BaseClasses { |
|
get; set; |
|
} |
|
|
|
public List<Method> Methods { |
|
get; set; |
|
} |
|
|
|
public List<Field> Fields { |
|
get; set; |
|
} |
|
|
|
public List<Property> Properties { |
|
get; set; |
|
} |
|
|
|
public bool Disable { |
|
get; set; |
|
} |
|
|
|
public CodeTypeDeclaration GenerateClass (Generator g, CodeTypeDeclaration libDecl, string libFieldName) { |
|
var decl = new CodeTypeDeclaration (Name); |
|
decl.IsPartial = true; |
|
if (BaseClasses.Count > 0) |
|
decl.BaseTypes.Add (new CodeTypeReference (BaseClasses [0].Name)); |
|
else |
|
decl.BaseTypes.Add (new CodeTypeReference ("ICppObject")); |
|
|
|
bool hasBase = BaseClasses.Count > 0; |
|
|
|
var layout = new CodeTypeDeclaration ("_" + Name); |
|
layout.IsStruct = true; |
|
layout.TypeAttributes = TypeAttributes.NotPublic; |
|
decl.Members.Add (layout); |
|
|
|
foreach (var f in Fields) { |
|
CodeMemberField field = new CodeMemberField { Name = f.Name, Type = g.CppTypeToCodeDomType (f.Type) }; |
|
layout.Members.Add (field); |
|
} |
|
|
|
var iface = new CodeTypeDeclaration ("I" + Name); |
|
iface.IsInterface = true; |
|
layout.TypeAttributes = TypeAttributes.NotPublic; |
|
iface.BaseTypes.Add (new CodeTypeReference ("ICppClassOverridable", new CodeTypeReference [] { new CodeTypeReference (decl.Name) })); |
|
decl.Members.Add (iface); |
|
|
|
var layoutField = new CodeMemberField (new CodeTypeReference (typeof (Type)), "native_layout"); |
|
layoutField.Attributes = MemberAttributes.Private|MemberAttributes.Static; |
|
layoutField.InitExpression = new CodeTypeOfExpression (layout.Name); |
|
decl.Members.Add (layoutField); |
|
|
|
var implField = new CodeMemberField (new CodeTypeReference (iface.Name), "impl"); |
|
implField.Attributes = MemberAttributes.Private|MemberAttributes.Static; |
|
var getclass = new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (libDecl.Name), libFieldName), "GetClass", new CodeTypeReference [] { new CodeTypeReference (iface.Name), new CodeTypeReference (layout.Name), new CodeTypeReference (decl.Name) }); |
|
implField.InitExpression = new CodeMethodInvokeExpression (getclass, new CodeExpression [] { new CodePrimitiveExpression (Name) }); |
|
decl.Members.Add (implField); |
|
//private static IClass impl = global::CppTests.Libs.Test.GetClass <IClass, _Class, Class>("Class"); |
|
|
|
if (!hasBase) { |
|
var ptrField = new CodeMemberField (new CodeTypeReference ("CppInstancePtr"), "native_ptr"); |
|
ptrField.Attributes = MemberAttributes.Family; |
|
decl.Members.Add (ptrField); |
|
} |
|
|
|
var allocCtor = new CodeConstructor () { |
|
}; |
|
allocCtor.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference ("CppLibrary"), "dummy")); |
|
allocCtor.Statements.Add (new CodeAssignStatement (new CodeFieldReferenceExpression (null, "native_ptr"), new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), "Alloc"), new CodeExpression [] { new CodeThisReferenceExpression () }))); |
|
if (hasBase) { |
|
var implTypeInfo = new CodeFieldReferenceExpression (new CodeFieldReferenceExpression { FieldName = "impl" }, "TypeInfo"); |
|
allocCtor.BaseConstructorArgs.Add (implTypeInfo); |
|
} |
|
decl.Members.Add (allocCtor); |
|
|
|
var subclassCtor = new CodeConstructor () { |
|
Attributes = MemberAttributes.Family |
|
}; |
|
subclassCtor.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference ("CppTypeInfo"), "subClass")); |
|
subclassCtor.Statements.Add (new CodeExpressionStatement (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeArgumentReferenceExpression ("subClass"), "AddBase"), new CodeExpression [] { new CodeFieldReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), "TypeInfo") }))); |
|
if (hasBase) { |
|
var implTypeInfo = new CodeFieldReferenceExpression (new CodeFieldReferenceExpression { FieldName = "impl" }, "TypeInfo"); |
|
subclassCtor.BaseConstructorArgs.Add (implTypeInfo); |
|
} |
|
decl.Members.Add (subclassCtor); |
|
|
|
if (!hasBase) { |
|
var nativeProperty = new CodeMemberProperty () { |
|
Name = "Native", |
|
Type = new CodeTypeReference ("CppInstancePtr"), |
|
Attributes = MemberAttributes.Public|MemberAttributes.Final |
|
}; |
|
nativeProperty.GetStatements.Add (new CodeMethodReturnStatement (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), "native_ptr"))); |
|
decl.Members.Add (nativeProperty); |
|
} |
|
|
|
var disposeMethod = new CodeMemberMethod () { |
|
Name = "Dispose", |
|
Attributes = MemberAttributes.Public |
|
}; |
|
if (Methods.Any (m => m.IsDestructor)) |
|
disposeMethod.Statements.Add (new CodeExpressionStatement (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), "Destruct"), new CodeExpression [] { new CodeFieldReferenceExpression (null, "Native") }))); |
|
disposeMethod.Statements.Add (new CodeExpressionStatement (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "Native"), "Dispose")))); |
|
decl.Members.Add (disposeMethod); |
|
|
|
foreach (Method m in Methods) { |
|
iface.Members.Add (m.GenerateIFaceMethod (g)); |
|
|
|
if (m.GenWrapperMethod) { |
|
var cm = m.GenerateWrapperMethod (g); |
|
if (m.IsConstructor && hasBase) { |
|
var implTypeInfo = new CodeFieldReferenceExpression (new CodeFieldReferenceExpression { FieldName = "impl" }, "TypeInfo"); |
|
(cm as CodeConstructor).BaseConstructorArgs.Add (implTypeInfo); |
|
} |
|
decl.Members.Add (cm); |
|
} |
|
} |
|
|
|
foreach (Property p in Properties) { |
|
decl.Members.Add (p.GenerateProperty (g)); |
|
} |
|
|
|
return decl; |
|
} |
|
}
|
|
|