Esempio n. 1
0
        public CXChildVisitResult Visit(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            if (cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            var cursorKind = clang.getCursorKind(cursor);

            // look only at function decls
            if (cursorKind == CXCursorKind.CXCursor_FunctionDecl)
            {
                var functionName = clang.getCursorSpelling(cursor).ToString();

                if (m_visitedFunctions.Contains(functionName))
                {
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }

                string libraryName;
                if (m_exportMap.TryGetValue(functionName, out libraryName))
                {
                    if (!string.Equals(libraryName, m_libraryName, StringComparison.InvariantCultureIgnoreCase))
                    {
                        string message = string.Format(@"Warning: Function {0} belongs to {1}. Skipping generation for {2}.",
                                                       functionName, libraryName, m_libraryName);
                        Console.WriteLine(message);
                        return(CXChildVisitResult.CXChildVisit_Continue);
                    }
                }
                else
                {
                    m_visitedFunctions.Add(functionName);

                    string message = string.Format(@"Info: Unknow function export {0}. Skipping generation for {1}.",
                                                   functionName, m_libraryName);
                    Console.WriteLine(message);
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }

                m_visitedFunctions.Add(functionName);

                WriteFunction(cursor, m_prefixStrip);

                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }
Esempio n. 2
0
        public CXChildVisitResult Visit(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            if (cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            var parents = new List <CXCursor> {
                parent
            };

            VisitInternal(cursor, parent, parents.ShallowCopy());

            return(CXChildVisitResult.CXChildVisit_Continue);
        }
Esempio n. 3
0
        public CXChildVisitResult Visit(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            if (cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            if (clang.equalCursors(cursor, this.beginningCursor) != 0)
            {
                this.beginningCursorReached = true;
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            if (this.beginningCursorReached)
            {
                this.ForwardDeclarationCursor = cursor;
                return(CXChildVisitResult.CXChildVisit_Break);
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }
Esempio n. 4
0
        public unsafe CXChildVisitResult Visit(CXCursor cursor, CXCursor parent, void *client_data)
        {
            if (!this.skipSystemHeaderCheck && cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            if (cursor.Equals(this.beginningCXCursor))
            {
                this.beginningCXCursorReached = true;
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            if (this.beginningCXCursorReached)
            {
                this.ForwardDeclarationCXCursor = cursor;
                return(CXChildVisitResult.CXChildVisit_Break);
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }
Esempio n. 5
0
        private CXChildVisitResult VisitCApi(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            if (cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            var kind = clang.getCursorKind(cursor);

            switch (kind)
            {
            case CXCursorKind.CXCursor_EnumDecl:
                var enumName = GetTypeAsString(clang.getCursorType(cursor));
                var baseType = clang.getEnumDeclIntegerType(cursor).kind.ToPrimitiveCsType() ?? "int";

                var enums = new List <KeyValuePair <string, long> >();
                clang.visitChildren(cursor, (cxCursor, parent1, clientData) =>
                {
                    var valName  = clang.getCursorSpelling(cxCursor).ToString();
                    var valValue = clang.getEnumConstantDeclValue(cxCursor);
                    enums.Add(new KeyValuePair <string, long>(valName, valValue));
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }, new CXClientData(IntPtr.Zero));

                WriteLine();

                var enumcs = GetCSharpName(enumName);
                WriteLine("public enum " + enumcs + (baseType != "int" ? " : " + baseType : string.Empty));
                WriteOpenBlock();
                foreach (var enumItem in enums)
                {
                    WriteLine(enumItem.Key + " = " + enumItem.Value + ",");
                }
                WriteCloseBlock();

                return(CXChildVisitResult.CXChildVisit_Continue);

            case CXCursorKind.CXCursor_StructDecl:
            case CXCursorKind.CXCursor_UnionDecl:
            {
                AddOpaqueStruct(cursor);

                // TODO: Check that a struct is either an opaque pointer (used only through a pointer)
                // or a real struct that we should generate fields for.

                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            case CXCursorKind.CXCursor_TypedefDecl:
            {
                var canonicalType = clang.getCanonicalType(clang.getTypedefDeclUnderlyingType(cursor));

                bool hasPointer = false;
                while (canonicalType.kind == CXTypeKind.CXType_Pointer)
                {
                    canonicalType = clang.getPointeeType(canonicalType);
                    hasPointer    = true;
                }

                if (canonicalType.kind == CXTypeKind.CXType_Record || hasPointer)
                {
                    AddOpaqueStruct(cursor);
                    // TODO: Check that a struct is either an opaque pointer (used only through a pointer)
                    // or a real struct that we should generate fields for.
                }

                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            case CXCursorKind.CXCursor_FunctionDecl:
                _writer = _writerBody;
                var functionName = clang.getCursorSpelling(cursor).ToString();

                var functionType = clang.getCursorType(cursor);
                WriteLine();

                WriteFunction(functionType, cursor, functionName);

                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }
        public CXChildVisitResult Visit(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            if (cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            CXCursorKind curKind = clang.getCursorKind(cursor);

            if (curKind == CXCursorKind.CXCursor_TypedefDecl)
            {
                var spelling = clang.getCursorSpelling(cursor).ToString();

                if (this.visitedTypeDefs.Contains(spelling))
                {
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }

                this.visitedTypeDefs.Add(spelling);

                CXType type = clang.getCanonicalType(clang.getTypedefDeclUnderlyingType(cursor));

                // we handle enums and records in struct and enum visitors with forward declarations also
                if (type.kind == CXTypeKind.CXType_Record || type.kind == CXTypeKind.CXType_Enum)
                {
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }

                // no idea what this is? -- template stuff?
                if (type.kind == CXTypeKind.CXType_Unexposed)
                {
                    var canonical = clang.getCanonicalType(type);
                    if (canonical.kind == CXTypeKind.CXType_Unexposed)
                    {
                        return(CXChildVisitResult.CXChildVisit_Continue);
                    }
                }

                if (type.kind == CXTypeKind.CXType_Pointer)
                {
                    var pointee = clang.getPointeeType(type);
                    if (pointee.kind == CXTypeKind.CXType_Record || pointee.kind == CXTypeKind.CXType_Void)
                    {
                        this.tw.WriteLine("    public partial struct " + spelling);
                        this.tw.WriteLine("    {");
                        this.tw.WriteLine("        public " + spelling + "(IntPtr pointer)");
                        this.tw.WriteLine("        {");
                        this.tw.WriteLine("            this.Pointer = pointer;");
                        this.tw.WriteLine("        }");
                        this.tw.WriteLine();
                        this.tw.WriteLine("        public IntPtr Pointer;");
                        this.tw.WriteLine("    }");
                        this.tw.WriteLine();

                        return(CXChildVisitResult.CXChildVisit_Continue);
                    }

                    if (pointee.kind == CXTypeKind.CXType_FunctionProto)
                    {
                        this.tw.WriteLine("    [UnmanagedFunctionPointer(" + pointee.CallingConventionSpelling() + ")]");
                        this.tw.Write("    public delegate ");
                        Extensions.ReturnTypeHelper(clang.getResultType(pointee), tw);
                        this.tw.Write(" ");
                        this.tw.Write(spelling);
                        this.tw.Write("(");

                        uint argumentCounter = 0;

                        clang.visitChildren(cursor, delegate(CXCursor cxCursor, CXCursor parent1, IntPtr ptr)
                        {
                            if (cxCursor.kind == CXCursorKind.CXCursor_ParmDecl)
                            {
                                Extensions.ArgumentHelper(pointee, cxCursor, tw, argumentCounter++);
                            }

                            return(CXChildVisitResult.CXChildVisit_Continue);
                        }, new CXClientData(IntPtr.Zero));

                        this.tw.WriteLine(");");
                        this.tw.WriteLine();

                        return(CXChildVisitResult.CXChildVisit_Continue);
                    }
                }

                if (clang.isPODType(type) != 0)
                {
                    var podType = type.ToPlainTypeString();
                    this.tw.WriteLine("    public partial struct " + spelling);
                    this.tw.WriteLine("    {");
                    this.tw.WriteLine("        public " + spelling + "(" + podType + " value)");
                    this.tw.WriteLine("        {");
                    this.tw.WriteLine("            this.Value = value;");
                    this.tw.WriteLine("        }");
                    this.tw.WriteLine();
                    this.tw.WriteLine("        public " + type.ToPlainTypeString() + " Value;");
                    this.tw.WriteLine("    }");
                    this.tw.WriteLine();
                }

                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }
Esempio n. 7
0
        public CXChildVisitResult Visit(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            if (cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            CXCursorKind curKind = clang.getCursorKind(cursor);

            if (curKind == CXCursorKind.CXCursor_EnumDecl)
            {
                string     inheritedEnumType;
                CXTypeKind kind = clang.getEnumDeclIntegerType(cursor).kind;

                switch (kind)
                {
                case CXTypeKind.CXType_Int:
                    inheritedEnumType = "int";
                    break;

                case CXTypeKind.CXType_UInt:
                    inheritedEnumType = "uint";
                    break;

                case CXTypeKind.CXType_Short:
                    inheritedEnumType = "short";
                    break;

                case CXTypeKind.CXType_UShort:
                    inheritedEnumType = "ushort";
                    break;

                case CXTypeKind.CXType_LongLong:
                    inheritedEnumType = "long";
                    break;

                case CXTypeKind.CXType_ULongLong:
                    inheritedEnumType = "ulong";
                    break;

                default:
                    inheritedEnumType = "int";
                    break;
                }

                var enumName = clang.getCursorSpelling(cursor).ToString();

                // enumName can be empty because of typedef enum { .. } enumName;
                // so we have to find the sibling, and this is the only way I've found
                // to do with libclang, maybe there is a better way?
                if (string.IsNullOrEmpty(enumName))
                {
                    var forwardDeclaringVisitor = new ForwardDeclarationVisitor(cursor);
                    clang.visitChildren(clang.getCursorLexicalParent(cursor), forwardDeclaringVisitor.Visit, new CXClientData(IntPtr.Zero));
                    enumName = clang.getCursorSpelling(forwardDeclaringVisitor.ForwardDeclarationCursor).ToString();

                    if (string.IsNullOrEmpty(enumName))
                    {
                        enumName = "_";
                    }
                }

                // if we've printed these previously, skip them
                if (this.printedEnums.Contains(enumName))
                {
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }

                this.printedEnums.Add(enumName);

                this.tw.WriteLine("    public enum " + enumName + " : " + inheritedEnumType);
                this.tw.WriteLine("    {");

                // visit all the enum values
                clang.visitChildren(cursor, (cxCursor, _, __) =>
                {
                    this.tw.WriteLine("        @" + clang.getCursorSpelling(cxCursor).ToString() + " = " + clang.getEnumConstantDeclValue(cxCursor) + ",");
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }, new CXClientData(IntPtr.Zero));

                this.tw.WriteLine("    }");
                this.tw.WriteLine();
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }
Esempio n. 8
0
        public CXChildVisitResult Visit(CXCursor cursor, CXCursor parent, IntPtr clientData)
        {
            if (cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            var cursorKind = clang.getCursorKind(cursor);

            if (cursorKind == CXCursorKind.CXCursor_StructDecl || cursorKind == CXCursorKind.CXCursor_UnionDecl)
            {
                if (m_writingStruct)
                {
                    Action defferedVisit = () => Visit(cursor, parent, clientData);
                    m_defferedVisits.Push(defferedVisit);
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }

                m_writingStruct = true;

                var structName = clang.getCursorSpelling(cursor).ToString();

                // struct names can be empty, and so we visit its sibling to find the name
                if (string.IsNullOrEmpty(structName))
                {
                    var forwardDeclaringVisitor = new ForwardDeclarationVisitor(cursor);
                    clang.visitChildren(clang.getCursorSemanticParent(cursor), forwardDeclaringVisitor.Visit, new CXClientData(IntPtr.Zero));
                    structName = clang.getCursorSpelling(forwardDeclaringVisitor.ForwardDeclarationCursor).ToString();

                    if (string.IsNullOrEmpty(structName))
                    {
                        structName = @"_";
                    }
                }

                if (!m_visitedStructs.Contains(structName))
                {
                    //m_tw.WriteLine(@"[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]");
                    m_tw.WriteLine(@"public unsafe partial struct " + structName);
                    m_tw.WriteLine(@"{");

                    m_hasChildren = false;

                    m_tw.Indent++;
                    clang.visitChildren(cursor, Visit, new CXClientData(IntPtr.Zero));
                    m_tw.Indent--;

                    m_tw.WriteLine(@"}");
                    m_tw.WriteLine();

                    if (m_hasChildren)
                    {
                        m_visitedStructs.Add(structName);
                    }
                }

                m_writingStruct = false;
                while (m_defferedVisits.Count > 0)
                {
                    var defferedVisit = m_defferedVisits.Pop();
                    defferedVisit();
                }

                //var fieldPosition = 0;

                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            if (cursorKind == CXCursorKind.CXCursor_FieldDecl)
            {
                m_hasChildren = true;

                var fieldName = clang.getCursorSpelling(cursor).ToString();
                if (string.IsNullOrEmpty(fieldName))
                {
                    throw new NotSupportedException();
                    //fieldName = @"field" + fieldPosition; // what if they have fields called field*? :)
                }

                //fieldPosition++;

                m_tw.WriteLine(ToMarshalString(cursor, fieldName));

                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }
Esempio n. 9
0
        public CXChildVisitResult Visit(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            if (cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            CXCursorKind curKind  = clang.getCursorKind(cursor);
            bool         isUnion  = (curKind == CXCursorKind.CXCursor_UnionDecl);
            bool         isStruct = (curKind == CXCursorKind.CXCursor_StructDecl);

            if (isUnion || isStruct)
            {
                this.fieldPosition = 0;
                var structName = clang.getCursorSpelling(cursor).ToString();

                // struct names can be empty, and so we visit its sibling to find the name
                if (string.IsNullOrEmpty(structName))
                {
                    var forwardDeclaringVisitor = new ForwardDeclarationVisitor(cursor);
                    clang.visitChildren(clang.getCursorSemanticParent(cursor), forwardDeclaringVisitor.Visit, new CXClientData(IntPtr.Zero));
                    structName = clang.getCursorSpelling(forwardDeclaringVisitor.ForwardDeclarationCursor).ToString();

                    if (string.IsNullOrEmpty(structName))
                    {
                        structName = "_";
                    }
                }

                if (!this.visitedStructs.Contains(structName))
                {
                    if (isUnion)
                    {
                        this.IndentedWriteLine("[StructLayout(LayoutKind.Explicit)]");
                    }
                    this.IndentedWriteLine("public partial struct " + structName);
                    this.IndentedWriteLine("{");

                    this.indentLevel++;
                    clang.visitChildren(cursor, this.Visit, new CXClientData(IntPtr.Zero));
                    this.indentLevel--;

                    this.IndentedWriteLine("}");
                    this.tw.WriteLine();

                    this.visitedStructs.Add(structName);
                }

                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            if (curKind == CXCursorKind.CXCursor_FieldDecl)
            {
                var fieldName = clang.getCursorSpelling(cursor).ToString();
                if (string.IsNullOrEmpty(fieldName))
                {
                    fieldName = "field" + this.fieldPosition; // what if they have fields called field*? :)
                }

                this.fieldPosition++;
                bool isUnionField = (clang.getCursorKind(parent) == CXCursorKind.CXCursor_UnionDecl);
                if (isUnionField)
                {
                    this.IndentedWriteLine("[FieldOffset(0)]");
                }
                if (fieldName == "padding")
                {
                    System.Diagnostics.Debugger.Break();
                }
                this.IndentedWriteLine(cursor.ToMarshalString(fieldName));
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }
Esempio n. 10
0
        public CXChildVisitResult Visit(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            if (cursor.IsInSystemHeader())
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            CXCursorKind curKind = clang.getCursorKind(cursor);

            if (curKind == CXCursorKind.CXCursor_EnumDecl)
            {
                string     inheritedEnumType;
                CXTypeKind kind = clang.getEnumDeclIntegerType(cursor).kind;

                switch (kind)
                {
                case CXTypeKind.CXType_Int:
                    inheritedEnumType = "int";
                    break;

                case CXTypeKind.CXType_UInt:
                    inheritedEnumType = "uint";
                    break;

                case CXTypeKind.CXType_Short:
                    inheritedEnumType = "short";
                    break;

                case CXTypeKind.CXType_UShort:
                    inheritedEnumType = "ushort";
                    break;

                case CXTypeKind.CXType_LongLong:
                    inheritedEnumType = "long";
                    break;

                case CXTypeKind.CXType_ULongLong:
                    inheritedEnumType = "ulong";
                    break;

                default:
                    inheritedEnumType = "int";
                    break;
                }

                // Cross-plat hack:
                // For whatever reason, libclang detects untyped enums (i.e. your average 'enum X { A, B }')
                // as uints on Linux and ints on Windows.
                // Since we want to have the same generated code everywhere, we try to force 'int'
                // if it doesn't change semantics, i.e. if all enum values are in the right range.
                // Remember that 2's complement ints use the same binary representation as uints for positive numbers.
                if (inheritedEnumType == "uint")
                {
                    bool hasOneValue = false;
                    long minValue    = long.MaxValue;
                    long maxValue    = long.MinValue;
                    clang.visitChildren(cursor, (cxCursor, _, __) =>
                    {
                        hasOneValue = true;

                        long value = clang.getEnumConstantDeclValue(cxCursor);
                        minValue   = Math.Min(minValue, value);
                        maxValue   = Math.Max(maxValue, value);

                        return(CXChildVisitResult.CXChildVisit_Continue);
                    }, new CXClientData(IntPtr.Zero));

                    if (hasOneValue && minValue >= 0 && maxValue <= int.MaxValue)
                    {
                        inheritedEnumType = "int";
                    }
                }

                var enumName = clang.getCursorSpelling(cursor).ToString();

                // enumName can be empty because of typedef enum { .. } enumName;
                // so we have to find the sibling, and this is the only way I've found
                // to do with libclang, maybe there is a better way?
                if (string.IsNullOrEmpty(enumName))
                {
                    var forwardDeclaringVisitor = new ForwardDeclarationVisitor(cursor);
                    clang.visitChildren(clang.getCursorLexicalParent(cursor), forwardDeclaringVisitor.Visit, new CXClientData(IntPtr.Zero));
                    enumName = clang.getCursorSpelling(forwardDeclaringVisitor.ForwardDeclarationCursor).ToString();

                    if (string.IsNullOrEmpty(enumName))
                    {
                        enumName = "_";
                    }
                }

                // if we've printed these previously, skip them
                if (this.printedEnums.Contains(enumName))
                {
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }

                this.printedEnums.Add(enumName);

                this.tw.WriteLine("    public enum " + enumName + " : " + inheritedEnumType);
                this.tw.WriteLine("    {");

                // visit all the enum values
                clang.visitChildren(cursor, (cxCursor, _, __) =>
                {
                    this.tw.WriteLine("        @" + clang.getCursorSpelling(cxCursor).ToString() + " = " + clang.getEnumConstantDeclValue(cxCursor) + ",");
                    return(CXChildVisitResult.CXChildVisit_Continue);
                }, new CXClientData(IntPtr.Zero));

                this.tw.WriteLine("    }");
                this.tw.WriteLine();
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }