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); }
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); }
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); } } }
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); } }
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; }
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); }
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); }
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); } }
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)); }
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); }
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 });
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(); } }
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(); } }
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); }
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); }
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()); }
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()); }
public static extern Cursor clang_getTypeDeclaration(CXType t);
public static extern Int64 clang_getArraySize(CXType t);
public static extern CXType clang_getResultType(CXType t);
public static bool IsPointer(this CXType type) { var t2 = type.Desugar(); return(t2.kind.IsPointer()); }
public static long GetArraySize(this CXType type) { return(clang.getArraySize(type)); }
public static extern CXType clang_getCanonicalType(CXType t);
public static extern Int64 clang_Type_getOffsetOf(CXType t, string s);
public static extern uint clang_isConstQualifiedType(CXType t);
public static extern Int64 clang_getNumElements(CXType t);
public static extern uint clang_isRestrictQualifiedType(CXType t);
public static extern uint clang_isVolatileQualifiedType(CXType t);
public static extern Int64 clang_Type_getAlignOf(CXType t);
public static extern CXType clang_Type_getClassType(CXType t);
public static extern Int64 clang_Type_getSizeOf(CXType t);
internal static extern ClangString clang_getTypeSpelling(CXType c);
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)); } }
public static extern uint clang_equalTypes(CXType a, CXType b);
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); }
public static extern CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType t);
public static string ToString(this CXType o) { return(clang.getTypeSpelling(o).ToString()); }
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); }
public static extern uint clang_isPODType(CXType t);
public static extern uint clang_isFunctionTypeVariadic(CXType t);
public static bool IsArray(this CXType type) { return(type.kind == CXTypeKind.CXType_ConstantArray || type.kind == CXTypeKind.CXType_DependentSizedArray || type.kind == CXTypeKind.CXType_VariableArray); }
public static extern int clang_getNumArgTypes(CXType t);
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); } }
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)); }
public static extern CXType clang_getArgType(CXType t, uint i);
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); }
public static extern CXType clang_getPointeeType(CXType t);
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); } } } }
public static extern CXCallingConv clang_getFunctionTypeCallingConv(CXType t);