Ejemplo n.º 1
0
        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));
        }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        /// <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);
        }