Example #1
0
        private static FunctionProto GetFunctionProto(AST ast, CXType funcType, TypeVisitContext context)
        {
            Debug.Assert(ClangTraits.IsFunction(funcType));
            FunctionProto proto = new FunctionProto();

            proto.ResultType = GetNativeType(ast, clang.getResultType(funcType), context);
            uint arity = (uint)clang.getNumArgTypes(funcType);

            for (uint loop = 0; loop < arity; ++loop)
            {
                CXType            argType = clang.getArgType(funcType, loop);
                FunctionParameter param   = new FunctionParameter();
                param.Type = GetNativeType(ast, argType, context);
                proto.AddParameter(param);
            }

            return(proto);
        }
Example #2
0
        public static bool IsCharPointer(this CXType type, int depth)
        {
            var pointee = type;

            for (int i = 0; i < depth; i++)
            {
                pointee = clang.getPointeeType(pointee);

                if (pointee.kind != CXTypeKind.CXType_Pointer)
                {
                    return(false);
                }
            }

            pointee = clang.getPointeeType(pointee);

            return(pointee.kind == CXTypeKind.CXType_Char_S);
        }
Example #3
0
        private static void ProcessTypeEntity(
            AST ast,
            NativeType type,
            CXType cxType,
            TypeVisitContext context)
        {
            type.IsConst = ClangTraits.IsConst(cxType);
            if (ClangTraits.IsBuiltInType(cxType))
            {
                type.SetBuiltin(ClangTraits.ToBasicType(cxType));
            }
            else
            {
                CXCursor cursor              = clang.getTypeDeclaration(cxType);
                CXType   theType             = clang.getCursorType(cursor);
                string   removeQualifierName = clang.getTypeSpelling(theType).ToString();

                if (ClangTraits.IsEnum(cxType))
                {
                    type.SetEnum(ast.GetEnum(removeQualifierName));
                }
                else if (ClangTraits.IsFunction(cxType))
                {
                    type.SetFunction(GetFunctionProto(ast, cxType, context));
                }
                else if (ClangTraits.IsUserDefiendType(cxType))
                {
                    NativeClass nativeClass = ast.GetClass(removeQualifierName);

                    // if native class is parsed already, the native class is a full specialization
                    // or the native class is a instantiation of a template or partial specialization
                    if (!nativeClass.IsClassEntity && !nativeClass.Parsed)
                    {
                        nativeClass.Parsed = true;
                        if (TemplateHelper.VisitTemplate(cursor, nativeClass, ast))
                        {
                            TemplateHelper.VisitTemplateParameter(cursor, theType, nativeClass, ast, context);
                        }
                    }

                    type.SetClass(nativeClass);
                }
            }
        }
Example #4
0
        private void ProcessClassDetail(
            NativeClass thisClass,              // this class to parse
            CXCursor cursor,                    // current cursor
            CXType type,                        // current cursor type
            CXCursor parent                     // parent cursor
            )
        {
            // set unscoped name
            thisClass.UnscopedName = clang.getCursorSpelling(cursor).ToString();

            // set struct or class
            thisClass.ClassTag = ClangTraits.ToStructOrClass(cursor.kind);

            // abstract
            thisClass.IsAbstract = clang.CXXRecord_isAbstract(cursor) != 0;

            // virtual base
            thisClass.IsVirtualBase = clang.isVirtualBase(cursor) != 0;

            // set template instance info
            if (TemplateHelper.VisitTemplate(cursor, thisClass, AST_))
            {
                thisClass.IsFullSpecialization = true;

                TypeVisitContext context = new TypeVisitContext(cursor);
                TemplateHelper.VisitTemplateParameter(cursor, type, thisClass, AST_, context);
            }

            // set subclass
            if (ClangTraits.IsUserDefinedTypeDecl(parent))
            {
                Debug.Assert(OwnerClass_ != null);
                thisClass.IsEmbedded = true;
                thisClass.OwnerClass = OwnerClass_;

                SubClass subClass = new SubClass
                {
                    Access = ClangTraits.ToAccessSpecifier(clang.getCXXAccessSpecifier(cursor)),
                    Class  = thisClass
                };

                OwnerClass_.AddSubClass(subClass);
            }
        }
Example #5
0
    public ClangExplorerNode(
        CKind kind,
        ClangLocation location,
        ClangExplorerNode?parent,
        CXCursor cursor,
        CXType type,
        CXType originalType,
        string?name,
        string?typeName)
    {
        Kind = kind;

        if (string.IsNullOrEmpty(location.FileName))
        {
            if (type.IsPrimitive())
            {
                // Primitives don't have a location
                Location = new ClangLocation
                {
                    FilePath   = string.Empty,
                    FileName   = "Builtin",
                    LineColumn = 0,
                    LineNumber = 0,
                    IsBuiltin  = true
                };
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        else
        {
            Location = location;
        }

        Parent       = parent;
        Cursor       = cursor;
        Type         = type;
        OriginalType = originalType;
        Name         = name;
        TypeName     = typeName;
    }
Example #6
0
        public unsafe static CodeTypeDelegate ToDelegate(this CXType type, string nativeName, CXCursor cursor, ModuleGenerator generator)
        {
            if (type.kind != CXTypeKind.CXType_FunctionProto &&
                type.kind != CXTypeKind.CXType_Unexposed)
            {
                throw new InvalidOperationException();
            }

            var clrName = NameConversions.ToClrName(nativeName, NameConversion.Type);

            CodeTypeDelegate delegateType = new CodeTypeDelegate();

            delegateType.CustomAttributes.Add(
                new CodeAttributeDeclaration(
                    new CodeTypeReference(typeof(UnmanagedFunctionPointerAttribute)),
                    new CodeAttributeArgument(
                        new CodePropertyReferenceExpression(
                            new CodeTypeReferenceExpression(typeof(CallingConvention)),
                            type.GetCallingConvention().ToString()))));

            delegateType.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            delegateType.Name       = clrName;
            delegateType.ReturnType = new CodeTypeReference(type.ResultType.ToClrType());

            uint argumentCounter = 0;

            var cursorVisitor = new DelegatingCXCursorVisitor(
                delegate(CXCursor c, CXCursor parent1)
            {
                if (c.Kind == CXCursorKind.CXCursor_ParmDecl)
                {
                    delegateType.Parameters.Add(Argument.GenerateArgument(generator, type, c, argumentCounter++, FunctionType.Delegate));
                }

                return(CXChildVisitResult.CXChildVisit_Continue);
            });

            cursor.VisitChildren(cursorVisitor.Visit, new CXClientData());

            return(delegateType);
        }
Example #7
0
        private void ProcessTypeExport(NativeClass thisClass, CXCursor cursor, CXCursor parent)
        {
            // createfield context
            TypeVisitContext context = new TypeVisitContext(cursor);

            // get field type
            CXType     type       = clang.getCursorType(cursor);
            NativeType nativeType = TypeVisitorHelper.GetNativeType(AST_, type, context);

            // get field access specifier
            AccessSpecifier access = ClangTraits.ToAccessSpecifier(clang.getCXXAccessSpecifier(cursor));

            // create the exported member type
            MemberType memberType = new MemberType
            {
                Access = access,
                Type   = nativeType
            };

            thisClass.AddMemberType(memberType);
        }
Example #8
0
        public static CXType GetPointeeType(this CXType type)
        {
            while (true)
            {
                type = type.Desugar();

                switch (type.kind)
                {
                case CXTypeKind.CXType_IncompleteArray:
                case CXTypeKind.CXType_ConstantArray:
                    type = clang.getArrayElementType(type);
                    continue;

                case CXTypeKind.CXType_Pointer:
                    type = clang.getPointeeType(type);
                    continue;
                }

                return(type);
            }
        }
Example #9
0
    string GetCSTypeName(CXType type, bool retval)
    {
        switch (type.kind)
        {
        case CXTypeKind.CXType_Void:
            return("void");

        case CXTypeKind.CXType_UInt:
            return("uint");

        case CXTypeKind.CXType_Bool:
            return("[MarshalAs(UnmanagedType.U1)]bool");
        }

        if (type.Declaration.IsInvalid)
        {
            return(type.Spelling.ToString());
        }

        return(GetDottedName(type.Declaration));
    }
Example #10
0
        private void ProcessBaseClass(NativeClass thisClass, CXCursor cursor, CXCursor parent)
        {
            // get class name
            CXType type = clang.getCursorType(cursor);

            // type visit context
            TypeVisitContext context = new TypeVisitContext(cursor);

            // create the base class
            BaseClass baseClass = new BaseClass
            {
                // check access specifier
                Access = ClangTraits.ToAccessSpecifier(clang.getCXXAccessSpecifier(cursor)),
                // native class type
                Type = TypeVisitorHelper.GetNativeType(AST_, type, context),
                // check is virtual base
                IsVirtual = clang.isVirtualBase(cursor) != 0
            };

            // register base class
            thisClass.AddBaseClass(baseClass);
        }
Example #11
0
 public static bool IsPrimitive(this CXType type)
 {
     return(type.kind switch
     {
         CXTypeKind.CXType_Void => true,
         CXTypeKind.CXType_Bool => true,
         CXTypeKind.CXType_Char_S => true,
         CXTypeKind.CXType_SChar => true,
         CXTypeKind.CXType_Char_U => true,
         CXTypeKind.CXType_UChar => true,
         CXTypeKind.CXType_UShort => true,
         CXTypeKind.CXType_UInt => true,
         CXTypeKind.CXType_ULong => true,
         CXTypeKind.CXType_ULongLong => true,
         CXTypeKind.CXType_Short => true,
         CXTypeKind.CXType_Int => true,
         CXTypeKind.CXType_Long => true,
         CXTypeKind.CXType_LongLong => true,
         CXTypeKind.CXType_Float => true,
         CXTypeKind.CXType_Double => true,
         _ => false
     });
Example #12
0
    public static bool IsSystem(this CXType type)
    {
        var kind = type.kind;

        if (type.IsPrimitive())
        {
            return(true);
        }

        switch (kind)
        {
        case CXTypeKind.CXType_Pointer:
            var pointeeType = clang_getPointeeType(type);
            return(IsSystem(pointeeType));

        case CXTypeKind.CXType_ConstantArray:
        case CXTypeKind.CXType_IncompleteArray:
            var elementType = clang_getElementType(type);
            return(IsSystem(elementType));

        case CXTypeKind.CXType_Typedef:
        case CXTypeKind.CXType_Elaborated:
        case CXTypeKind.CXType_Record:
        case CXTypeKind.CXType_Enum:
        case CXTypeKind.CXType_FunctionProto:
            var declaration = clang_getTypeDeclaration(type);
            return(IsSystem(declaration));

        case CXTypeKind.CXType_FunctionNoProto:
            return(false);

        case CXTypeKind.CXType_Attributed:
            var modifiedType = clang_Type_getModifiedType(type);
            return(IsSystem(modifiedType));

        default:
            throw new NotImplementedException();
        }
    }
Example #13
0
        public static bool IsSystemType(this CXType type)
        {
            var kind = type.kind;

            switch (kind)
            {
            case CXTypeKind.CXType_Void:
            case CXTypeKind.CXType_Bool:
            case CXTypeKind.CXType_Char_S:
            case CXTypeKind.CXType_Char_U:
            case CXTypeKind.CXType_UChar:
            case CXTypeKind.CXType_UShort:
            case CXTypeKind.CXType_UInt:
            case CXTypeKind.CXType_ULong:
            case CXTypeKind.CXType_ULongLong:
            case CXTypeKind.CXType_Short:
            case CXTypeKind.CXType_Int:
            case CXTypeKind.CXType_Long:
            case CXTypeKind.CXType_LongLong:
            case CXTypeKind.CXType_Float:
            case CXTypeKind.CXType_Double:
                return(true);

            case CXTypeKind.CXType_Pointer:
                return(IsSystemType(type.PointeeType));

            case CXTypeKind.CXType_ConstantArray:
            case CXTypeKind.CXType_Typedef:
            case CXTypeKind.CXType_Elaborated:
            case CXTypeKind.CXType_Record:
            case CXTypeKind.CXType_Enum:
            case CXTypeKind.CXType_FunctionProto:
                return(IsSystemCursor(type.Declaration));

            default:
                throw new NotImplementedException();
            }
        }
Example #14
0
        private void ProcessField(NativeClass thisClass, CXCursor cursor, CXCursor parent, bool isStatic = false)
        {
            // get field name
            string fieldName = clang.getCursorSpelling(cursor).ToString();

            // get field type
            CXType     type       = clang.getCursorType(cursor);
            NativeType nativeType = TypeVisitorHelper.GetNativeType(AST_, type);

            // get field access specifier
            AccessSpecifier access = ClangTraits.ToAccessSpecifier(clang.getCXXAccessSpecifier(cursor));

            // create field object
            Field f = new Field
            {
                Name     = fieldName,
                Access   = access,
                Type     = nativeType,
                IsStatic = isStatic
            };

            thisClass.AddField(f);
        }
Example #15
0
        private static void ProcessReferencePointer(AST ast, NativeType type, CXType cxType, TypeVisitContext context)
        {
            Debug.Assert(type.TypeKind == BasicType.Unknown);
            type.IsConst = ClangTraits.IsConst(cxType);

            CXType     pointeeType = clang.getPointeeType(cxType);
            NativeType nativeType  = GetNativeType(ast, pointeeType, context);

            if (ClangTraits.IsLValueReference(cxType))
            {
                type.SetTypeLValRef(nativeType);
            }
            else if (ClangTraits.IsRValueReference(cxType))
            {
                type.SetTypeRValRef(nativeType);
            }
            else if (ClangTraits.IsPointer(cxType))
            {
                type.SetPointer(nativeType);
            }

            Debug.Assert(type.TypeKind != BasicType.Unknown);
        }
        private static CXTypeKind CanonizeType(ref CXType type, out CXCursor typeDeclCursor)
        {
            //var originalType = type;
            typeDeclCursor = clang.getTypeDeclaration(type);

            /*
             * var typeName = type.ToString();
             * switch (typeName) {
             *      case "size_t": {
             *              return CXTypeKind.CXType_UInt128;
             *      }
             *      case "ptrdiff_t": {
             *              return CXTypeKind.CXType_Int128;
             *      }
             * }
             */
            if (type.kind == CXTypeKind.CXType_Typedef)
            {
                if (IsCursorInSystemHeader(typeDeclCursor))
                {
                    type = clang.getCanonicalType(type);
                }
                for (; ;)
                {
                    var underlyingType = clang.getTypedefDeclUnderlyingType(typeDeclCursor);
                    if (underlyingType.kind != CXTypeKind.CXType_Invalid)
                    {
                        type           = underlyingType;
                        typeDeclCursor = clang.getTypeDeclaration(type);
                        continue;
                    }
                    break;
                }
            }

            return(type.kind);
        }
Example #17
0
        private static string ProcessPointerType(this CXType type, bool treatArrayAsPointer)
        {
            type = type.Desugar();

            if (type.kind == CXTypeKind.CXType_Void)
            {
                return("*mut u8");
            }

            var sb = new StringBuilder();

            if (type.kind.IsPrimitiveNumericType())
            {
                sb.Append("*mut ");
            }
            else
            {
                sb.Append("*mut ");
            }

            sb.Append(ToCSharpTypeString(type, treatArrayAsPointer));

            return(sb.ToString());
        }
Example #18
0
        private static string ProcessPointerType(this CXType type, bool treatArrayAsPointer)
        {
            type = type.Desugar();

            if (type.kind == CXTypeKind.CXType_Void)
            {
                return("void *");
            }

            var sb = new StringBuilder();

            sb.Append(ToCSharpTypeString(type, treatArrayAsPointer));

            RecordType recordType;
            string     recordName;

            type.ResolveRecord(out recordType, out recordName);
            if (recordType != RecordType.Class)
            {
                sb.Append("*");
            }

            return(sb.ToString());
        }
Example #19
0
 public static extern Cursor clang_getTypeDeclaration(CXType t);
Example #20
0
 public static extern Int64 clang_getArraySize(CXType t);
Example #21
0
 public static extern CXType clang_getResultType(CXType t);
Example #22
0
        public static bool IsPointer(this CXType type)
        {
            var t2 = type.Desugar();

            return(t2.kind.IsPointer());
        }
Example #23
0
 public static long GetArraySize(this CXType type)
 {
     return(clang.getArraySize(type));
 }
Example #24
0
 public static extern CXType clang_getCanonicalType(CXType t);
Example #25
0
 public static extern Int64 clang_Type_getOffsetOf(CXType t, string s);
Example #26
0
 public static extern uint clang_isConstQualifiedType(CXType t);
Example #27
0
 public static extern Int64 clang_getNumElements(CXType t);
Example #28
0
 public static extern uint clang_isRestrictQualifiedType(CXType t);
Example #29
0
 public static extern uint clang_isVolatileQualifiedType(CXType t);
Example #30
0
 public static extern Int64 clang_Type_getAlignOf(CXType t);
Example #31
0
 public static extern CXType clang_Type_getClassType(CXType t);
Example #32
0
 public static extern Int64 clang_Type_getSizeOf(CXType t);
Example #33
0
 internal static extern ClangString clang_getTypeSpelling(CXType c);
Example #34
0
        public static Type ToPlainType(this CXType type)
        {
            switch (type.kind)
            {
            case CXTypeKind.CXType_Pointer:
                return(type.IsPtrToConstChar() ? typeof(string) : typeof(IntPtr));    // const char* gets special treatment

            case CXTypeKind.CXType_Bool:
                return(typeof(bool));

            case CXTypeKind.CXType_UChar:
            case CXTypeKind.CXType_Char_U:
                return(typeof(byte));

            case CXTypeKind.CXType_SChar:
            case CXTypeKind.CXType_Char_S:
                return(typeof(sbyte));

            case CXTypeKind.CXType_UShort:
                return(typeof(ushort));

            case CXTypeKind.CXType_Short:
                return(typeof(short));

            case CXTypeKind.CXType_Float:
                return(typeof(float));

            case CXTypeKind.CXType_Double:
                return(typeof(double));

            case CXTypeKind.CXType_Int:
                return(typeof(int));

            case CXTypeKind.CXType_UInt:
                return(typeof(uint));

            case CXTypeKind.CXType_NullPtr:     // ugh, what else can I do?
                return(typeof(IntPtr));

            case CXTypeKind.CXType_Long:
                return(typeof(int));

            case CXTypeKind.CXType_ULong:
                return(typeof(int));

            case CXTypeKind.CXType_LongLong:
                return(typeof(long));

            case CXTypeKind.CXType_ULongLong:
                return(typeof(ulong));

            case CXTypeKind.CXType_Void:
                return(typeof(void));

            //case CXTypeKind.CXType_IncompleteArray: //TODO: Fix incompleteArray
            //    return TypeTranslate(clang.getArrayElementType(type)) + "[]";
            case CXTypeKind.CXType_Unexposed:
                var canonical = clang.getCanonicalType(type);
                if (canonical.kind == CXTypeKind.CXType_Unexposed)
                {
                    Console.WriteLine("ToType Unexposed:" + canonical);
                    return(typeof(IntPtr));
                }
                return(canonical.ToPlainType());

            default:
                return(typeof(IntPtr));
            }
        }
Example #35
0
 public static extern uint clang_equalTypes(CXType a, CXType b);
Example #36
0
        public static string ToCSharpTypeString(this CXType type, bool treatArrayAsPointer = false, bool replace = true)
        {
            var isConstQualifiedType = clang.isConstQualifiedType(type) != 0;
            var spelling             = string.Empty;

            var sb = new StringBuilder();

            type = type.Desugar();
            switch (type.kind)
            {
            case CXTypeKind.CXType_Record:
                spelling = clang.getTypeSpelling(type).ToString();
                break;

            case CXTypeKind.CXType_IncompleteArray:
                sb.Append(clang.getArrayElementType(type).ToCSharpTypeString());
                spelling = "[]";
                break;

            case CXTypeKind.CXType_Unexposed:                     // Often these are enums and canonical type gets you the enum spelling
                var canonical = clang.getCanonicalType(type);
                // unexposed decl which turns into a function proto seems to be an un-typedef'd fn pointer
                spelling = canonical.kind == CXTypeKind.CXType_FunctionProto
                                                ? "IntPtr"
                                                : clang.getTypeSpelling(canonical).ToString();
                break;

            case CXTypeKind.CXType_ConstantArray:
                var t = clang.getArrayElementType(type);
                if (treatArrayAsPointer)
                {
                    sb.Append(ProcessPointerType(t, true));
                }
                else
                {
                    if (!Parameters.GenerateSafeCode ||
                        (Parameters.Classes != null && Parameters.Classes.Contains(t.ToCSharpTypeString(false, false))))
                    {
                        sb.Append(t.ToCSharpTypeString() + "[]");
                    }
                    else
                    {
                        sb.Append(t.ToCSharpTypeString().WrapIntoFakePtr());
                    }
                }
                break;

            case CXTypeKind.CXType_Pointer:
                sb.Append(ProcessPointerType(clang.getPointeeType(type), treatArrayAsPointer));
                break;

            default:
                spelling = clang.getCanonicalType(type).ToPlainTypeString();
                break;
            }

            if (isConstQualifiedType)
            {
                spelling = spelling.Replace("const ", string.Empty);                 // ugh
            }

            spelling = spelling.Replace("struct ", string.Empty);

            if (spelling.StartsWith("enum "))
            {
                spelling = "int";
            }

            if (replace && Parameters.TypeNameReplacer != null)
            {
                spelling = Parameters.TypeNameReplacer(spelling);
            }

            sb.Append(spelling);
            return(sb.ToString());
        }
        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);
        }
Example #38
0
 public static extern CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType t);
Example #39
0
 public static string ToString(this CXType o)
 {
     return(clang.getTypeSpelling(o).ToString());
 }
Example #40
0
        private CppParameter GetFunctionParamMarshalType(CXType parameterType)
        {
            var param = new CppParameter();

            if (parameterType.kind == CXTypeKind.CXType_Unexposed)
            {
                parameterType = clang.getCanonicalType(parameterType);
            }

            var typeName = clang.getTypeSpelling(parameterType).ToString();

            if (typeName == "size_t")
            {
                param.Type = "size_t";
                return(param);
            }

            if (parameterType.kind == CXTypeKind.CXType_Pointer)
            {
                var pointeeType = clang.getPointeeType(parameterType);
                if (pointeeType.kind == CXTypeKind.CXType_Unexposed)
                {
                    pointeeType = clang.getCanonicalType(pointeeType);
                }

                if (pointeeType.kind == CXTypeKind.CXType_Typedef)
                {
                    var finalPointeeType = clang.getCanonicalType(pointeeType);
                    if (finalPointeeType.kind == CXTypeKind.CXType_Record)
                    {
                        param.Type = GetCSharpName(clang.getTypeSpelling(pointeeType).ToString());
                        return(param);
                    }
                    pointeeType = finalPointeeType;
                }

                if (pointeeType.kind == CXTypeKind.CXType_Record)
                {
                    param.Type = GetCSharpName(clang.getTypeSpelling(pointeeType).ToString());
                }
                else if (pointeeType.kind == CXTypeKind.CXType_Enum)
                {
                    param.Qualifier = "out";
                    param.Type      = clang.getTypeSpelling(pointeeType).ToString();
                }
                else if (pointeeType.kind.IsChar())
                {
                    param.Type = "StringUtf8";
                }
                else
                {
                    param.Type = "IntPtr";
                }
                return(param);
            }
            if (parameterType.kind == CXTypeKind.CXType_Typedef)
            {
                var finalPointeeType = clang.getCanonicalType(parameterType);

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

                if (finalPointeeType.kind == CXTypeKind.CXType_Record || hasPointer)
                {
                    param.Type = GetCSharpName(clang.getTypeSpelling(parameterType).ToString());
                    return(param);
                }
                parameterType = clang.getCanonicalType(parameterType);
            }
            else if (parameterType.kind == CXTypeKind.CXType_Enum)
            {
                param.Type = GetCSharpName(clang.getTypeSpelling(parameterType).ToString());
                return(param);
            }

            param.Type = parameterType.kind.ToPrimitiveCsType();
            return(param);
        }
Example #41
0
 public static extern uint clang_isPODType(CXType t);
Example #42
0
 public static extern uint clang_isFunctionTypeVariadic(CXType t);
Example #43
0
 public static bool IsArray(this CXType type)
 {
     return(type.kind == CXTypeKind.CXType_ConstantArray ||
            type.kind == CXTypeKind.CXType_DependentSizedArray ||
            type.kind == CXTypeKind.CXType_VariableArray);
 }
Example #44
0
 public static extern int clang_getNumArgTypes(CXType t);
Example #45
0
        public static string ToPlainTypeString(this CXType type, string unknownType = "UnknownType")
        {
            var canonical = clang.getCanonicalType(type);

            switch (type.kind)
            {
            case CXTypeKind.CXType_Bool:
                return("bool");

            case CXTypeKind.CXType_UChar:
            case CXTypeKind.CXType_Char_U:
                return("char");

            case CXTypeKind.CXType_SChar:
            case CXTypeKind.CXType_Char_S:
                return("sbyte");

            case CXTypeKind.CXType_UShort:
                return("ushort");

            case CXTypeKind.CXType_Short:
                return("short");

            case CXTypeKind.CXType_Float:
                return("float");

            case CXTypeKind.CXType_Double:
                return("double");

            case CXTypeKind.CXType_Int:
                return("int");

            case CXTypeKind.CXType_UInt:
                return("uint");

            case CXTypeKind.CXType_Pointer:
            case CXTypeKind.CXType_NullPtr:     // ugh, what else can I do?
                return("IntPtr");

            case CXTypeKind.CXType_Long:
                return("int");

            case CXTypeKind.CXType_ULong:
                return("int");

            case CXTypeKind.CXType_LongLong:
                return("long");

            case CXTypeKind.CXType_ULongLong:
                return("ulong");

            case CXTypeKind.CXType_Void:
                return("void");

            case CXTypeKind.CXType_Unexposed:
                if (canonical.kind == CXTypeKind.CXType_Unexposed)
                {
                    return(clang.getTypeSpelling(canonical).ToString());
                }
                return(canonical.ToPlainTypeString());

            default:
                return(unknownType);
            }
        }
Example #46
0
 public static extern CXType clang_getArrayElementType(CXType t);
        private ParameterInfo ResolveParameter(CXType originalType, string name = null, int index = 0)
        {
            string renamed;
            var    type = originalType;

            if (type.kind == CXTypeKind.CXType_FunctionProto)
            {
                throw new NotImplementedException();
            }
            if (type.kind == CXTypeKind.CXType_FunctionNoProto)
            {
                throw new NotImplementedException();
            }
            var typeKind = CanonizeType(ref type, out var typeDeclCursor);

            if (typeKind == CXTypeKind.CXType_Pointer)
            {
                var pointeeType = clang.getPointeeType(type);
                if (clang.getFunctionTypeCallingConv(pointeeType) != CXCallingConv.CXCallingConv_Invalid)
                {
                    var delegateTypeName     = originalType.ToString();
                    var possibleDelegateType = Module.GetType(delegateTypeName);
                    if (possibleDelegateType != null)
                    {
                        return(new ParameterInfo(name, possibleDelegateType, index));
                    }

                    return(new ParameterInfo(name,
                                             IncompleteTypeReference.Get(Module, null, delegateTypeName), index));
                }
                var resolvedParameter = ResolveParameter(pointeeType);
                return(new ParameterInfo(name,
                                         resolvedParameter.Type.MakePointerType(), index));
            }
            if (typeKind == CXTypeKind.CXType_DependentSizedArray)
            {
                throw new NotImplementedException();
            }
            if (typeKind == CXTypeKind.CXType_ConstantArray)
            {
                var arraySize         = (int)clang.getArraySize(type);
                var elementType       = clang.getArrayElementType(type);
                var resolvedParameter = ResolveParameter(elementType, name);
                var clrElementType    = resolvedParameter.Type;
                if (clrElementType.IsPointer)
                {
                    clrElementType = Module.TypeSystem.IntPtr;
                }
                var arrayType = resolvedParameter.Type.MakeArrayType();

                if (!PrimitiveUnmanagedTypeMap.TryGetValue(clrElementType.GetRuntimeType(), out var unmanagedType))
                {
                    throw new NotImplementedException();
                }

                return(new ParameterInfo(name,
                                         arrayType, index, ParameterAttributes.None, arraySize));
            }
            if (PrimitiveTypeMap.TryGetValue(typeKind, out var primitiveType))
            {
                if (primitiveType == null)
                {
                    throw new NotImplementedException();
                }
                var originalTypeName = originalType.ToString();
                var typeName         = originalTypeName;

                if (TypeRedirects.TryGetValue(originalTypeName, out renamed))
                {
                    typeName = renamed;
                }
                if (originalType.kind == CXTypeKind.CXType_Typedef)
                {
                    if (KnownTypes.ContainsKey(typeName))
                    {
                        var knownType = Module.GetType(typeName)
                                        ?? Module.GetType(originalTypeName)
                                        ?? throw new NotImplementedException();
                        return(new ParameterInfo(name, knownType, index));
                    }
                }
                else
                {
                    var found = Module.GetType(typeName);
                    if (found != null)
                    {
                        return(new ParameterInfo(name, found, index));
                    }
                }

                return(new ParameterInfo(name, primitiveType.Import(Module), index));
            }

            var typeDeclName = typeDeclCursor.ToString();

            if (TypeRedirects.TryGetValue(typeDeclName, out renamed))
            {
                typeDeclName = renamed;
            }

            var possibleType = Module.GetType(typeDeclName);

            if (possibleType != null)
            {
                return(new ParameterInfo(name, possibleType, index));
            }

            return(new ParameterInfo(name,
                                     IncompleteTypeReference.Get(Module, null, typeDeclName), index));
        }
Example #48
0
 public static extern CXType clang_getArgType(CXType t, uint i);
Example #49
0
        public static CodeParameterDeclarationExpression GenerateArgument(this ModuleGenerator generator, CXType functionType, CXCursor paramCXCursor, uint index, FunctionType functionKind)
        {
            var numArgTypes = functionType.NumArgTypes;
            var type        = functionType.GetArgType(index);
            var cursorType  = paramCXCursor.Type;

            var name = paramCXCursor.Spelling.CString;

            if (string.IsNullOrEmpty(name))
            {
                name = "param" + index;
            }

            name = NameConversions.ToClrName(name, NameConversion.Parameter);

            CodeParameterDeclarationExpression parameter = new CodeParameterDeclarationExpression();

            parameter.Name = name;

            bool isPointer = false;

            if (functionKind != FunctionType.Free &&
                functionKind != FunctionType.Delegate &&
                type.IsDoubleCharPointer() &&
                !name.Contains("data") &&
                name != "appids")
            {
                parameter.Type      = new CodeTypeReference(typeof(string));
                parameter.Direction = FieldDirection.Out;

                parameter.CustomAttributes.Add(MarshalAsUtf8String());
            }
            else if (functionKind != FunctionType.Delegate && type.IsTripleCharPointer() && generator.StringArrayMarshalerType != null)
            {
                parameter.Type      = new CodeTypeReference(typeof(ReadOnlyCollection <string>));
                parameter.Direction = FieldDirection.Out;

                parameter.CustomAttributes.Add(MarshalAsDeclaration(UnmanagedType.CustomMarshaler, new CodeTypeReference(generator.StringArrayMarshalerType.Name)));
            }
            else if (functionKind != FunctionType.Delegate && (type.IsArrayOfCharPointers() || type.IsDoublePtrToConstChar()))
            {
                parameter.Type      = new CodeTypeReference(typeof(ReadOnlyCollection <string>));
                parameter.Direction = FieldDirection.In;

                parameter.CustomAttributes.Add(MarshalAsUtf8StringArray());
            }
            else
            {
                switch (type.kind)
                {
                case CXTypeKind.CXType_Pointer:
                    var pointee = type.PointeeType;
                    switch (pointee.kind)
                    {
                    case CXTypeKind.CXType_Pointer:
                        parameter.Type = new CodeTypeReference(typeof(IntPtr));
                        isPointer      = true;
                        break;

                    case CXTypeKind.CXType_FunctionProto:
                        parameter.Type = new CodeTypeReference(cursorType.ToClrType());
                        break;

                    case CXTypeKind.CXType_Void:
                        parameter.Type = new CodeTypeReference(typeof(IntPtr));
                        break;

                    case CXTypeKind.CXType_Char_S:
                        // In some of the read/write functions, const char is also used to represent data -- in that
                        // case, it maps to a byte[] array or just an IntPtr.
                        if (functionKind != FunctionType.PInvoke && type.IsPtrToConstChar())
                        {
                            if (!name.Contains("data") && name != "signature")
                            {
                                parameter.Type = new CodeTypeReference(typeof(string));
                                parameter.CustomAttributes.Add(MarshalAsDeclaration(UnmanagedType.LPStr));
                            }
                            else
                            {
                                parameter.Type = new CodeTypeReference(typeof(byte[]));
                            }
                        }
                        else if (functionKind != FunctionType.PInvoke && functionKind != FunctionType.Delegate && type.IsPtrToChar() && name.Contains("data"))
                        {
                            parameter.Type = new CodeTypeReference(typeof(byte[]));
                        }
                        else
                        {
                            // if it's not a const, it's best to go with IntPtr
                            parameter.Type = new CodeTypeReference(typeof(IntPtr));
                        }

                        break;

                    case CXTypeKind.CXType_WChar:
                        if (type.IsPtrToConstChar())
                        {
                            parameter.Type = new CodeTypeReference(typeof(string));
                            parameter.CustomAttributes.Add(MarshalAsDeclaration(UnmanagedType.LPWStr));
                        }
                        else
                        {
                            parameter.Type = new CodeTypeReference(typeof(IntPtr));
                        }

                        break;

                    case CXTypeKind.CXType_Record:
                        if (functionKind != FunctionType.Delegate)
                        {
                            var recordTypeCXCursor = pointee.Declaration;
                            var recordType         = recordTypeCXCursor.Type;

                            // Get the CLR name for the record
                            var clrName = generator.NameMapping[recordType.Spelling.CString.ToString()];
                            parameter.Type = new CodeTypeReference(clrName);
                            isPointer      = true;
                        }
                        else
                        {
                            // if it's not a const, it's best to go with IntPtr
                            parameter.Type = new CodeTypeReference(typeof(IntPtr));
                            isPointer      = true;
                        }

                        break;

                    default:
                        parameter.Type = pointee.ToCodeTypeReference(paramCXCursor, generator);
                        isPointer      = true;
                        break;
                    }

                    break;

                default:
                    if (generator.NameMapping.ContainsKey(type.Spelling.CString.ToString()))
                    {
                        if (functionKind != FunctionType.Delegate)
                        {
                            parameter.Type = type.ToCodeTypeReference(paramCXCursor, generator);
                        }
                        else
                        {
                            parameter.Type = new CodeTypeReference(typeof(IntPtr));
                        }
                    }
                    else
                    {
                        parameter.Type = type.ToCodeTypeReference(paramCXCursor, generator);
                    }

                    break;
                }
            }

            if (functionKind == FunctionType.Delegate && parameter.Type.BaseType.EndsWith("Handle"))
            {
                // Use a custom marshaler
                parameter.CustomAttributes.Add(
                    MarshalAsDeclaration(
                        UnmanagedType.CustomMarshaler,
                        new CodeTypeReference(parameter.Type.BaseType + "DelegateMarshaler")));
            }

            if (isPointer)
            {
                switch (functionKind)
                {
                case FunctionType.None:
                case FunctionType.Delegate:
                    if (parameter.Type.BaseType.EndsWith("Handle"))
                    {
                        // Handles are always out parameters
                        parameter.Direction = FieldDirection.Out;
                    }
                    else
                    {
                        // For IntPtrs, we don't know - so we play on the safe side.
                        parameter.Direction = FieldDirection.Ref;
                    }

                    break;

                case FunctionType.New:
                case FunctionType.PInvoke:
                    parameter.Direction = FieldDirection.Out;
                    break;

                case FunctionType.Free:
                    parameter.Direction = FieldDirection.In;
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }

            return(parameter);
        }
Example #50
0
 public static extern CXType clang_getPointeeType(CXType t);
Example #51
0
        protected override void VisitChild(VisitorCursor cursor, List <VisitorCursor> parents)
        {
            if (cursor.Kind == CXCursorKind.CXCursor_TypedefDecl)
            {
                if (config.NativeDelegates.Any(i => i.Name == cursor.Spelling) && !info.Delegates.Any(i => i.Name == cursor.Spelling))
                {
                    CXType type    = clang.getCanonicalType(clang.getTypedefDeclUnderlyingType(cursor.Cursor));
                    var    pointee = clang.getPointeeType(type);
                    if (pointee.kind == CXTypeKind.CXType_FunctionProto)
                    {
                        var callingConv = clang.getFunctionTypeCallingConv(pointee);
                        var returnType  = clang.getResultType(pointee);
                        var name        = cursor.Spelling;

                        var delegateDecl = new IDescribeMethod
                        {
                            Name    = cursor.Spelling,
                            Returns = new List <IDescribeReturn> {
                                new IDescribeReturn {
                                    Type = returnType.ToPlainType()
                                }
                            },
                        };


                        CodeAttributeArgument arg;
                        switch (callingConv)
                        {
                        case CXCallingConv.CXCallingConv_X86StdCall:
                        case CXCallingConv.CXCallingConv_X86_64Win64:
                            arg = new CodeAttributeArgument(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(CallingConvention)), "StdCall"));
                            break;

                        default:
                            arg = new CodeAttributeArgument(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(CallingConvention)), "Cdecl"));
                            break;
                        }


                        uint parmCounter = 0;
                        cursor.VisitChildren((childCursor) =>
                        {
                            if (childCursor.Kind == CXCursorKind.CXCursor_ParmDecl)
                            {
                                var paramType     = clang.getArgType(pointee, parmCounter);
                                var paramSpelling = childCursor.Spelling;
                                if (string.IsNullOrEmpty(paramSpelling))
                                {
                                    paramSpelling = "param" + parmCounter;
                                }

                                delegateDecl.Arguments.Add(new IDescribeArgument {
                                    Name = paramSpelling, Type = paramType.ToPlainType()
                                });

                                parmCounter++;
                            }
                        });

                        if (delegateDecl.Arguments.Any(a => a.Type == typeof(string)) || delegateDecl.Returns.Any(a => a.Type == typeof(string)))
                        {
                            delegateDecl.Attributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(UnmanagedFunctionPointerAttribute)), arg,
                                                                                     new CodeAttributeArgument(nameof(UnmanagedFunctionPointerAttribute.CharSet), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(CharSet)), nameof(CharSet.Ansi)))));
                        }
                        else
                        {
                            delegateDecl.Attributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(UnmanagedFunctionPointerAttribute)), arg));
                        }

                        info.Delegates.Add(delegateDecl);
                    }
                }
            }
        }
Example #52
0
 public static extern CXCallingConv clang_getFunctionTypeCallingConv(CXType t);