public override bool VisitCppConstructor(CppConstructor cppConstructor) { Declaration classDecl; cppElementToDeclarationMapping.TryGetValue(cppConstructor.Parent, out classDecl); Class @class = classDecl != null ? classDecl as Class : FindDeclParent <Class>(cppConstructor.Parent); Method method = new Method(); method.Kind = CXXMethodKind.Constructor; method.Access = AccessSpecifier.Public; method.Name = cppConstructor.Name; method.Namespace = @class.Namespace; // Check for default constructor if (cppConstructor.Parameters.Count() == 0) { method.IsDefaultConstructor = true; } // Check for copy constructor if ((cppConstructor.Parameters.Count() == 1) && (cppConstructor.Parameters.First().TypeName == cppConstructor.Name)) { method.IsCopyConstructor = true; } @class.Methods.Add(method); cppElementToDeclarationMapping.Add(cppConstructor, method); return(base.VisitCppConstructor(cppConstructor)); }
/// <summary> /// Parses a C++ constructor. /// </summary> private CppConstructor ParseConstructor(XElement xElement) { CppConstructor cppConstructor = new CppConstructor(); cppConstructor.Name = xElement.Attribute("name").Value; cppConstructor.Id = xElement.Attribute("id").Value; // Parse parameters ParseParameters(xElement, cppConstructor); return(cppConstructor); }
private CXChildVisitResult VisitMethod(CXCursor cursor, CXCursor parent, IntPtr data) { Unit unitParent = units[parent]; string unitName = clang.getCString(clang.getCursorSpelling(cursor)); CXCursorKind unitKind = clang.getCursorKind(cursor); CppMethod unit; if (unitKind == CXCursorKind.CXCursor_Constructor && unitParent is CppType) { unit = new CppConstructor(unitParent as CppType); } else if (unitKind == CXCursorKind.CXCursor_Destructor && unitParent is CppType) { unit = new CppDestructor(unitParent as CppType); } else { unit = new CppMethod(unitParent, unitName); } // Find modifiers if (unitParent is Type && modifiers.ContainsKey(unitParent as Type)) { unit.modifiers = modifiers[unitParent as Type]; } if (clang.CXXMethod_isStatic(cursor) > 0) { unit.modifiers |= Modifiers.Static; } // Find result type if (unitKind != CXCursorKind.CXCursor_Constructor && unitKind != CXCursorKind.CXCursor_Destructor) { CXType result = clang.getCursorResultType(cursor); unit.result = FromCXType(result, GetAllTemplates(unitParent).Concat(new[] { unitParent as Type })); } // Merge with properties /*if (unitName.StartsWith("Get") || unitName.StartsWith("Set")) * { * CppField property = properties.FirstOrDefault(p => p.Name == unitName.Substring(3) && p.Parent == unitParent) as CppField; * if (property != null) * { * if (unitName.StartsWith("Get")) * property.getAccessor = unit; * else * property.setAccessor = unit; * } * }*/ // Parse templates int startPosition = unitName.IndexOf('<'); int stopPosition = startPosition == -1 ? -1 : unitName.IndexOf('>', startPosition); if (startPosition >= 0 && stopPosition >= 0) { string[] typeStrings = unitName.Substring(startPosition, stopPosition - startPosition).Split(',').Select(t => t.Trim()).ToArray(); foreach (string typeString in typeStrings) { unit.templates.Add(CppType.GetReference(typeString)); } if (unitParent is Type) { foreach (Type type in (unitParent as Type).Templates) { unit.templates.RemoveAll(t => t.Equals(type)); } } } units.Add(cursor, unit); if (unitParent is CppType) { (unitParent as CppType).methods.Add(unit); } return(CXChildVisitResult.CXChildVisit_Recurse); }
/// <summary> /// Parse C++ class or interface from given <see cref="XElement"/> /// </summary> private T ParseClassOrInterface <T>(XElement xElement) where T : CppBase, new() { // If element is already transformed, return it T cppBaseType = xElement.Annotation <T>(); if (cppBaseType != null) { return(cppBaseType); } // Else, create a new CppInterface cppBaseType = new T(); cppBaseType.Name = xElement.Attribute("name").Value; cppBaseType.Id = xElement.Attribute("id").Value; xElement.AddAnnotation(cppBaseType); // Calculate offsets using inheritance int offsetMethod = 0; int offsetConstructor = 0; XAttribute basesAttribute = xElement.Attribute("bases"); IEnumerable <string> bases = basesAttribute != null?basesAttribute.Value.Split(' ') : Enumerable.Empty <string>(); foreach (string xElementBaseId in bases) { if (string.IsNullOrEmpty(xElementBaseId)) { continue; } XElement xElementBase = mapIdToXElement[xElementBaseId]; CppElement cppElementBase = ParseElement(xElementBase); if (string.IsNullOrEmpty(cppBaseType.ParentName)) { cppBaseType.ParentName = cppElementBase.Name; } // Get methods count from base class or interface offsetMethod += ((cppElementBase is CppBase) ? ((CppBase)cppElementBase).TotalMethodCount : 0); offsetConstructor += ((cppElementBase is CppBase) ? ((CppBase)cppElementBase).TotalConstructorCount : 0); } List <CppConstructor> constructors = new List <CppConstructor>(); List <CppMethod> methods = new List <CppMethod>(); // Parse methods foreach (XElement element in xElement.Elements()) { string overrides = String.Empty; XAttribute overridesAttribute = element.Attribute("overrides"); if (overridesAttribute != null) { overrides = overridesAttribute.Value; } string pureVirtual = String.Empty; XAttribute pureVirtualAttribute = element.Attribute("pure_virtual"); if (pureVirtualAttribute != null) { pureVirtual = pureVirtualAttribute.Value; } string access = String.Empty; XAttribute accessAttribute = element.Attribute("access"); if (accessAttribute != null) { access = accessAttribute.Value; } // Parse method with pure virtual (=0) and that do not override any other methods if (element.Name.LocalName == "Method") { CppMethod cppMethod = ParseMethodOrFunction <CppMethod>(element); if (!string.IsNullOrWhiteSpace(pureVirtual)) { cppMethod.Virtual = true; } if (!string.IsNullOrWhiteSpace(overrides)) { cppMethod.Override = true; } if (!string.IsNullOrWhiteSpace(access)) { cppMethod.Access = access; } methods.Add(cppMethod); } else if (element.Name.LocalName == "Constructor") { CppConstructor cppConstructor = ParseConstructor(element); if (!string.IsNullOrWhiteSpace(access)) { cppConstructor.Access = access; } constructors.Add(cppConstructor); } } // The Visual C++ compiler breaks the rules of the COM ABI when overloaded methods are used. // It will group the overloads together in memory and lay them out in the reverse of their declaration order. // Since GCC always lays them out in the order declared, we have to modify the order of the methods to match Visual C++. // See http://support.microsoft.com/kb/131104 for more information. for (int i = 0; i < methods.Count; i++) { string name = methods[i].Name; // Look for overloads of this function for (int j = i + 1; j < methods.Count; j++) { var nextMethod = methods[j]; if (nextMethod.Name == name) { // Remove this one from its current position further into the vtable methods.RemoveAt(j); // Put this one before all other overloads (aka reverse declaration order) int k = i - 1; while (k >= 0 && methods[k].Name == name) { k--; } methods.Insert(k + 1, nextMethod); i++; } } } // Add the methods to the cppbase with the correct offsets foreach (CppMethod cppMethod in methods) { cppMethod.Offset = offsetMethod++; cppBaseType.Add(cppMethod); } // Add the constructor to the cppbase with the correct offsets foreach (CppConstructor cppConstructor in constructors) { cppConstructor.Offset = offsetConstructor++; cppBaseType.Add(cppConstructor); } cppBaseType.TotalConstructorCount = offsetConstructor; cppBaseType.TotalMethodCount = offsetMethod; return(cppBaseType); }