public override bool VisitFieldDecl(Field field) { if (!VisitDeclaration(field)) return false; var type = field.Type; Declaration decl; type.TryGetDeclaration(out decl); string msg = "internal"; if (decl == null || (decl.GenerationKind != GenerationKind.Internal && !HasInvalidType(type, out msg))) return false; field.GenerationKind = GenerationKind.Internal; var @class = (Class)field.Namespace; var cppTypePrinter = new CppTypePrinter(); var typeName = type.Visit(cppTypePrinter); Log.Debug("Field '{0}::{1}' was ignored due to {2} type '{3}'", @class.Name, field.Name, msg, typeName); return true; }
private bool IsStdType(QualifiedType type) { var typePrinter = new CppTypePrinter(Driver.TypeDatabase); var typeName = type.Visit(typePrinter); return typeName.Contains("std::"); }
public void TestPrintingSpecializationWithConstValue() { var template = AstContext.FindDecl <ClassTemplate>("TestSpecializationArguments").First(); var cppTypePrinter = new CppTypePrinter { ScopeKind = TypePrintScopeKind.Qualified }; Assert.That(template.Specializations.Last().Visit(cppTypePrinter).Type, Is.EqualTo("TestSpecializationArguments<const TestASTEnumItemByName>")); }
public void TestPrintNestedInSpecialization() { var template = AstContext.FindDecl <ClassTemplate>("TestTemplateClass").First(); var cppTypePrinter = new CppTypePrinter { ScopeKind = TypePrintScopeKind.Qualified }; Assert.That(template.Specializations[3].Classes.First().Visit(cppTypePrinter).Type, Is.EqualTo("TestTemplateClass<Math::Complex>::NestedInTemplate")); }
public void TestPrintQualifiedSpecialization() { var functionWithSpecializationArg = AstContext.FindFunction("functionWithSpecializationArg").First(); var cppTypePrinter = new CppTypePrinter { ScopeKind = TypePrintScopeKind.Qualified }; Assert.That(functionWithSpecializationArg.Parameters[0].Visit(cppTypePrinter).Type, Is.EqualTo("const TestTemplateClass<int>")); }
public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals) { if (!VisitType(pointer, quals)) { return(false); } var pointee = pointer.Pointee.Desugar(); if (pointee is FunctionType) { var cppTypePrinter = new CppTypePrinter(); var cppTypeName = pointer.Visit(cppTypePrinter, quals); return(VisitDelegateType(cppTypeName)); } Enumeration @enum; if (pointee.TryGetEnum(out @enum)) { var isRef = Context.Parameter.Usage == ParameterUsage.Out || Context.Parameter.Usage == ParameterUsage.InOut; ArgumentPrefix.Write("&"); Context.Return.Write("(::{0}){1}{2}", @enum.QualifiedOriginalName, isRef ? string.Empty : "*", Context.Parameter.Name); return(true); } Class @class; if (pointee.TryGetClass(out @class) && @class.IsValueType) { if (Context.Function == null) { Context.Return.Write("&"); } return(pointer.QualifiedPointee.Visit(this)); } var finalPointee = pointer.GetFinalPointee(); if (finalPointee.IsPrimitiveType()) { var cppTypePrinter = new CppTypePrinter(); var cppTypeName = pointer.Visit(cppTypePrinter, quals); Context.Return.Write("({0})", cppTypeName); Context.Return.Write(Context.Parameter.Name); return(true); } return(pointer.QualifiedPointee.Visit(this)); }
public SymbolsCodeGenerator(BindingContext context, IEnumerable <TranslationUnit> units) : base(context, units) { cppTypePrinter = new CppTypePrinter(Context) { ScopeKind = TypePrintScopeKind.Qualified, ResolveTypedefs = true }; cppTypePrinter.PushContext(TypePrinterContextKind.Native); }
public override bool VisitEnumDecl(Enumeration @enum) { var typePrinter = new CppTypePrinter(Context.Context); typePrinter.PushContext(TypePrinterContextKind.Managed); var typeName = typePrinter.VisitDeclaration(@enum); Context.Return.Write($"({typeName}){Context.ReturnVarName}"); return(true); }
public void TestVolatile() { var cppTypePrinter = new CppTypePrinter { PrintScopeKind = TypePrintScopeKind.Qualified }; var builtin = new BuiltinType(PrimitiveType.Char); var pointee = new QualifiedType(builtin, new TypeQualifiers { IsConst = true, IsVolatile = true }); var type = pointee.Visit(cppTypePrinter); Assert.That(type, Is.EqualTo("const volatile char")); }
public override bool VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals) { if (AlreadyVisited(template) || template.Template.Access == AccessSpecifier.Private) return false; if (template.Arguments.Select(a => a.Type.Type.Desugar()).All(t => t.IsAddress() && !t.GetFinalPointee().IsDependent)) { var cppTypePrinter = new CppTypePrinter { PrintScopeKind = CppTypePrintScopeKind.Qualified }; templateInstantiations.Add(string.Format("{0}<{1}>", template.Template.Name, string.Join(", ", template.Arguments.Select(a => a.Type.Type.Visit(cppTypePrinter))))); } return true; }
public override void CLIMarshalToNative(MarshalContext ctx) { var templateType = Type as TemplateSpecializationType; var type = templateType.Arguments[0].Type; var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name : ctx.ArgName; var tmpVarName = "_tmp" + entryString; var cppTypePrinter = new CppTypePrinter(ctx.Driver.TypeDatabase); var nativeType = type.Type.Visit(cppTypePrinter); ctx.SupportBefore.WriteLine("auto {0} = std::vector<{1}>();", tmpVarName, nativeType); ctx.SupportBefore.WriteLine("for each({0} _element in {1})", type.ToString(), entryString); ctx.SupportBefore.WriteStartBraceIndent(); { var param = new Parameter { Name = "_element", QualifiedType = type }; var elementCtx = new MarshalContext(ctx.Driver) { Parameter = param, ArgName = param.Name, }; var marshal = new CLIMarshalManagedToNativePrinter(elementCtx); type.Type.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) { ctx.SupportBefore.Write(marshal.Context.SupportBefore); } ctx.SupportBefore.WriteLine("auto _marshalElement = {0};", marshal.Context.Return); ctx.SupportBefore.WriteLine("{0}.push_back(_marshalElement);", tmpVarName); } ctx.SupportBefore.WriteCloseBraceIndent(); ctx.Return.Write(tmpVarName); }
public override bool VisitFieldDecl(Field field) { if (field.Ignore) return false; var typePrinter = new CppTypePrinter(Driver.TypeDatabase); var typeName = field.QualifiedType.Visit(typePrinter); if (!typeName.Contains("std::")) return false; field.ExplicityIgnored = true; return true; }
public void TestPrintingConstPointerWithConstType() { var cppTypePrinter = new CppTypePrinter { PrintScopeKind = TypePrintScopeKind.Qualified }; var builtin = new BuiltinType(PrimitiveType.Char); var pointee = new QualifiedType(builtin, new TypeQualifiers { IsConst = true }); var pointer = new QualifiedType(new PointerType(pointee), new TypeQualifiers { IsConst = true }); var type = pointer.Visit(cppTypePrinter); Assert.That(type, Is.EqualTo("const char* const")); }
public void TestPrintingConstPointerWithConstType() { var template = AstContext.FindDecl <ClassTemplate>("TestSpecializationArguments").First(); var cppTypePrinter = new CppTypePrinter { PrintScopeKind = CppTypePrintScopeKind.Qualified }; var builtin = new BuiltinType(PrimitiveType.Char); var pointee = new QualifiedType(builtin, new TypeQualifiers { IsConst = true }); var pointer = new QualifiedType(new PointerType(pointee), new TypeQualifiers { IsConst = true }); var type = pointer.Visit(cppTypePrinter); Assert.AreEqual(type, "const char* const"); }
public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals) { var decl = typedef.Declaration; TypeMap typeMap; if (Context.Context.TypeMaps.FindTypeMap(decl.Type, out typeMap) && typeMap.DoesMarshalling) { typeMap.CppMarshalToNative(Context); return(typeMap.IsValueType); } FunctionType func; if (decl.Type.IsPointerTo(out func)) { var typePrinter = new CppTypePrinter(Context.Context); typePrinter.PushContext(TypePrinterContextKind.Native); var declName = decl.Visit(typePrinter); typePrinter.PopContext(); // Use the original typedef name if available, otherwise just use the function pointer type string cppTypeName; if (!decl.IsSynthetized) { cppTypeName = "::" + typedef.Declaration.QualifiedOriginalName; } else { cppTypeName = decl.Type.Visit(typePrinter, quals); } VisitDelegateType(cppTypeName); return(true); } PrimitiveType primitive; if (decl.Type.IsPrimitiveType(out primitive)) { Context.Return.Write($"(::{typedef.Declaration.QualifiedOriginalName})"); } return(decl.Type.Visit(this)); }
public override bool VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals) { if (AlreadyVisited(template) || template.Template.Access == AccessSpecifier.Private) { return(false); } if (template.Arguments.Select(a => a.Type.Type.Desugar()).All(t => t.IsAddress() && !t.GetFinalPointee().IsDependent)) { var cppTypePrinter = new CppTypePrinter { PrintScopeKind = CppTypePrintScopeKind.Qualified }; templateInstantiations.Add(string.Format("{0}<{1}>", template.Template.Name, string.Join(", ", template.Arguments.Select(a => a.Type.Type.Visit(cppTypePrinter))))); } return(true); }
public Documentation(string docsPath, string module, Dictionary<Type, List<TypedefDecl>> typeDefsPerType) { this.documentation = Get(docsPath, module); CppTypePrinter cppTypePrinter = new CppTypePrinter(new TypeMapDatabase()); cppTypePrinter.PrintKind = CppTypePrintKind.Local; this.typeDefsPerType = new Dictionary<string, List<TypedefDecl>>(); foreach (KeyValuePair<Type, List<TypedefDecl>> typeTypeDefs in typeDefsPerType) { if (!(typeTypeDefs.Key is DependentNameType) && !(typeTypeDefs.Key is InjectedClassNameType)) { string typeName = typeTypeDefs.Key.Visit(cppTypePrinter); if (!this.typeDefsPerType.ContainsKey(typeName)) { this.typeDefsPerType.Add(typeName, typeTypeDefs.Value); } } } }
public override bool VisitFieldDecl(Field field) { if (field.Ignore) { return(false); } var typePrinter = new CppTypePrinter(Driver.TypeDatabase); var typeName = field.QualifiedType.Visit(typePrinter); if (!typeName.Contains("std::")) { return(false); } field.ExplicityIgnored = true; return(true); }
private static void DisableSingleTypeMap(Class mapped, BindingContext context) { var names = new List <string> { mapped.OriginalName }; foreach (TypePrintScopeKind kind in Enum.GetValues(typeof(TypePrintScopeKind))) { var cppTypePrinter = new CppTypePrinter { ScopeKind = kind }; names.Add(mapped.Visit(cppTypePrinter)); } foreach (var name in names.Where(context.TypeMaps.TypeMaps.ContainsKey)) { context.TypeMaps.TypeMaps[name].IsEnabled = false; } }
private bool TryMatch(Function function, string docs, bool markObsolete, bool completeSignature = true) { const string memberDoc = @"\n{{2}}(\[(\w+\s*)+\] )?([\w :*&<>,]+)?(({0}(\s*&)?::)| ){1}(const)?( \[(\w+\s*)+\])?\n(?<docs>\w.*?)(\n\s*){{1,2}}((\n\s*){{2}})"; const string separator = @",\s*"; StringBuilder signatureRegex = new StringBuilder(Regex.Escape(function.OriginalName)).Append(@"\s*\(\s*("); bool anyArgs = false; CppTypePrinter cppTypePrinter = new CppTypePrinter(new TypeMapDatabase()); cppTypePrinter.PrintScopeKind = CppTypePrintScopeKind.Local; foreach (string argType in function.Parameters.Where(p => p.Kind == ParameterKind.Regular).Select(p => p.Type.Visit(cppTypePrinter))) { if (!anyArgs) { signatureRegex.Append("?<args>"); anyArgs = true; } signatureRegex.Append(this.GetTypeRegex(argType, completeSignature)).Append(@"(\s+\w+(\s*=\s*[^,\r\n]+(\(\s*\))?)?)?"); signatureRegex.Append(separator); } if (anyArgs) { signatureRegex.Insert(signatureRegex.Length - separator.Length, '('); } else { signatureRegex.Append('('); } signatureRegex.Append(@"[\w :*&<>]+\s*=\s*[^,\r\n]+(\(\s*\))?(,\s*)?)*)\s*(,\s*\.{3}\s*)?\)\s*"); Match match = Regex.Match(docs, string.Format(memberDoc, function.Namespace.Name, signatureRegex), RegexOptions.Singleline | RegexOptions.ExplicitCapture); if (match.Success) { function.Comment = new RawComment(); function.Comment.BriefText = match.Groups["docs"].Value; FillMissingParameterNames(function, match.Groups["args"].Value); if (markObsolete) { AddObsoleteAttribute(function); } return(true); } return(false); }
public Documentation(string docsPath, string module, Dictionary <Type, List <TypedefDecl> > typeDefsPerType) { this.documentation = Get(docsPath, module); CppTypePrinter cppTypePrinter = new CppTypePrinter(new TypeMapDatabase()); cppTypePrinter.PrintScopeKind = CppTypePrintScopeKind.Local; this.typeDefsPerType = new Dictionary <string, List <TypedefDecl> >(); foreach (KeyValuePair <Type, List <TypedefDecl> > typeTypeDefs in typeDefsPerType) { if (!(typeTypeDefs.Key is DependentNameType) && !(typeTypeDefs.Key is InjectedClassNameType)) { string typeName = typeTypeDefs.Key.Visit(cppTypePrinter); if (!this.typeDefsPerType.ContainsKey(typeName)) { this.typeDefsPerType.Add(typeName, typeTypeDefs.Value); } } } }
private void DocumentQtProperty(Property property) { string file = GetFileForDeclarationContext(property.Namespace); if (this.documentation.ContainsKey(file)) { string docs = this.documentation[file]; CppTypePrinter cppTypePrinter = new CppTypePrinter(new TypeMapDatabase()); cppTypePrinter.PrintScopeKind = CppTypePrintScopeKind.Local; string type = property.Type.Visit(cppTypePrinter); Match match = Regex.Match(docs, "Property Documentation.*" + property.Name + @" : (const )?(\w+::)?" + type.Replace("*", @"\s*\*") + @"(\s+const)?\n(?<docs>.*?)\nAccess functions:", RegexOptions.Singleline | RegexOptions.ExplicitCapture); if (match.Success) { property.Comment = new RawComment(); property.Comment.BriefText = match.Groups["docs"].Value; } } }
public void TestPrintingConstPointerWithConstType() { var cppTypePrinter = new CppTypePrinter(Context) { ResolveTypeMaps = false }; cppTypePrinter.PushScope(TypePrintScopeKind.Qualified); var builtin = new BuiltinType(PrimitiveType.Char); var pointee = new QualifiedType(builtin, new TypeQualifiers { IsConst = true }); var pointer = new QualifiedType(new PointerType(pointee), new TypeQualifiers { IsConst = true }); string type = pointer.Visit(cppTypePrinter); Assert.That(type, Is.EqualTo("const char* const")); }
public override bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization) { if (!specialization.IsDependent && (!specialization.TranslationUnit.IsSystemHeader || specialization.IsSupportedStdSpecialization())) { var cppTypePrinter = new CppTypePrinter { PrintScopeKind = CppTypePrintScopeKind.Qualified, PrintLogicalNames = true }; var cppCode = specialization.Visit(cppTypePrinter); var module = specialization.TranslationUnit.Module; if (templateInstantiations.ContainsKey(module)) templateInstantiations[module].Add(cppCode); else templateInstantiations.Add(module, new HashSet<string> { cppCode }); } return true; }
void GenerateGetHashCode(Class @class, Block block) { var hashcodeOverride = @class.Methods.FirstOrDefault(m => { var expansions = m.PreprocessedEntities.OfType <MacroExpansion>(); return(expansions.Any(e => e.Text == "FLD_HASHCODE")); }); if (hashcodeOverride == null) { return; } var cppTypePrinter = new CppTypePrinter(Driver.TypeDatabase); var classCppType = @class.Visit(cppTypePrinter); block.Text.StringBuilder.Clear(); block.WriteLine("return (({0}*)NativePtr)->{1}();", classCppType, hashcodeOverride.OriginalName); }
public void HandleRefOutNonDefaultIntegerEnum(Enumeration @enum) { // This deals with marshaling of managed enums with non-C default // backing types (ie. enum : short). // Unlike C++ or Objective-C, C enums always have the default integer // type size, so we need to create a local variable of the right type // for marshaling with the managed runtime and cast it back to the // correct type. var backingType = @enum.BuiltinType.Type; var typePrinter = new CppTypePrinter(); var integerType = typePrinter.VisitPrimitiveType(backingType); var newArgName = CGenerator.GenId(Context.ArgName); Context.SupportBefore.WriteLine("{0} {1} = *(({0}*) {2});", integerType, newArgName, Context.ArgName); Context.Return.Write("&{0}", newArgName); Context.SupportAfter.WriteLine("*{0} = ({1}) {2};", Context.ArgName, @enum.QualifiedName, newArgName); }
public override void GenerateClassEvents(Class @class) { foreach (var @event in @class.Events) { if ([email protected]) { continue; } var cppTypePrinter = new CppTypePrinter(Context); cppTypePrinter.PushContext(TypePrinterContextKind.Native); var cppArgs = cppTypePrinter.VisitParameters(@event.Parameters, hasNames: true); WriteLine("private:"); Indent(); var delegateName = string.Format("_{0}Delegate", @event.Name); WriteLine("delegate void {0}({1});", delegateName, cppArgs); WriteLine("{0}^ {0}Instance;", delegateName); WriteLine("void _{0}Raise({1});", @event.Name, cppArgs); WriteLine("{0} _{1};", @event.Type, @event.Name); Unindent(); WriteLine("public:"); Indent(); WriteLine("event {0} {1}", @event.Type, @event.Name); WriteOpenBraceAndIndent(); WriteLine("void add({0} evt);", @event.Type); WriteLine("void remove({0} evt);", @event.Type); var cliTypePrinter = new CLITypePrinter(Context); var cliArgs = cliTypePrinter.VisitParameters(@event.Parameters, hasNames: true); WriteLine("void raise({0});", cliArgs); UnindentAndWriteCloseBrace(); Unindent(); } }
public override bool VisitClassDecl(Class @class) { if (!base.VisitClassDecl(@class) || [email protected]) return false; var cppTypePrinter = new CppTypePrinter { PrintScopeKind = CppTypePrintScopeKind.Qualified, PrintLogicalNames = true }; foreach (var specialization in @class.Specializations.Where(s => !s.IsDependent && !s.Ignore)) { var cppCode = specialization.Visit(cppTypePrinter); var module = specialization.TranslationUnit.Module; if (templateInstantiations.ContainsKey(module)) templateInstantiations[module].Add(cppCode); else templateInstantiations.Add(module, new HashSet<string> { cppCode }); } return true; }
public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals) { var pointee = pointer.Pointee; if ((pointee.IsPrimitiveType(PrimitiveType.Char) || pointee.IsPrimitiveType(PrimitiveType.WideChar)) && pointer.QualifiedPointee.Qualifiers.IsConst) { Context.SupportBefore.WriteLine( "auto _{0} = clix::marshalString<clix::E_UTF8>({1});", Context.ArgName, Context.Parameter.Name); Context.Return.Write("_{0}.c_str()", Context.ArgName); return(true); } if (pointee is FunctionType) { var function = pointee as FunctionType; var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypeName = pointer.Visit(cppTypePrinter, quals); return(VisitDelegateType(function, cppTypeName)); } PrimitiveType primitive; if (pointee.Desugar().IsPrimitiveType(out primitive)) { var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypeName = pointer.Visit(cppTypePrinter, quals); Context.Return.Write("({0})", cppTypeName); Context.Return.Write("{0}.ToPointer()", Context.Parameter.Name); return(true); } return(pointee.Visit(this, quals)); }
public void GenerateClassEvents(Class @class) { foreach (var @event in @class.Events) { if ([email protected]) { continue; } var cppTypePrinter = new CppTypePrinter(Driver.TypeDatabase); var cppArgs = cppTypePrinter.VisitParameters(@event.Parameters, hasNames: true); WriteLine("private:"); PushIndent(); var delegateName = string.Format("_{0}Delegate", @event.Name); WriteLine("delegate void {0}({1});", delegateName, cppArgs); WriteLine("{0}^ {0}Instance;", delegateName); WriteLine("void _{0}Raise({1});", @event.Name, cppArgs); WriteLine("{0} _{1};", @event.Type, @event.Name); PopIndent(); WriteLine("public:"); PushIndent(); WriteLine("event {0} {1}", @event.Type, @event.Name); WriteStartBraceIndent(); WriteLine("void add({0} evt);", @event.Type); WriteLine("void remove({0} evt);", @event.Type); var cliTypePrinter = new CLITypePrinter(Driver); var cliArgs = cliTypePrinter.VisitParameters(@event.Parameters, hasNames: true); WriteLine("void raise({0});", cliArgs); WriteCloseBraceIndent(); PopIndent(); } }
void SetupTypePrinter() { CppSharp.AST.Type.TypePrinterDelegate = type => { CppTypePrintFlavorKind kind = CppTypePrintFlavorKind.Cpp; switch (Options.GeneratorKind) { case GeneratorKind.C: kind = CppTypePrintFlavorKind.C; break; case GeneratorKind.ObjectiveC: kind = CppTypePrintFlavorKind.ObjC; break; } var typePrinter = new CppTypePrinter { PrintFlavorKind = kind }; return(type.Visit(typePrinter)); }; }
public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals) { var decl = typedef.Declaration; TypeMap typeMap; if (Context.Driver.TypeDatabase.FindTypeMap(decl, out typeMap) && typeMap.DoesMarshalling) { typeMap.CLIMarshalToNative(Context); return typeMap.IsValueType; } FunctionType func; if (decl.Type.IsPointerTo(out func)) { // Use the original typedef name if available, otherwise just use the function pointer type string cppTypeName; if (!decl.IsSynthetized) cppTypeName = "::" + typedef.Declaration.QualifiedOriginalName; else { var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); cppTypeName = decl.Type.Visit(cppTypePrinter, quals); } VisitDelegateType(func, cppTypeName); return true; } PrimitiveType primitive; if (decl.Type.IsPrimitiveType(out primitive)) { Context.Return.Write("(::{0})", typedef.Declaration.QualifiedOriginalName); } return decl.Type.Visit(this); }
public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals) { if (!VisitType(pointer, quals)) return false; var pointee = pointer.Pointee.Desugar(); if ((pointee.IsPrimitiveType(PrimitiveType.Char) || pointee.IsPrimitiveType(PrimitiveType.WideChar)) && pointer.QualifiedPointee.Qualifiers.IsConst) { Context.SupportBefore.WriteLine( "auto _{0} = clix::marshalString<clix::E_UTF8>({1});", Context.ArgName, Context.Parameter.Name); Context.Return.Write("_{0}.c_str()", Context.ArgName); return true; } if (pointee is FunctionType) { var function = pointee as FunctionType; var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypeName = pointer.Visit(cppTypePrinter, quals); return VisitDelegateType(function, cppTypeName); } Enumeration @enum; if (pointee.TryGetEnum(out @enum)) { var isRef = Context.Parameter.Usage == ParameterUsage.Out || Context.Parameter.Usage == ParameterUsage.InOut; ArgumentPrefix.Write("&"); Context.Return.Write("(::{0}){1}{2}", @enum.QualifiedOriginalName, isRef ? string.Empty : "*", Context.Parameter.Name); return true; } Class @class; if (pointee.TryGetClass(out @class) && @class.IsValueType) { if (Context.Function == null) Context.Return.Write("&"); return pointee.Visit(this, quals); } var finalPointee = pointer.GetFinalPointee(); if (finalPointee.IsPrimitiveType()) { var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypeName = pointer.Visit(cppTypePrinter, quals); Context.Return.Write("({0})", cppTypeName); Context.Return.Write(Context.Parameter.Name); return true; } return pointer.Pointee.Visit(this, quals); }
public override void CLIMarshalToNative(MarshalContext ctx) { var templateType = Type as TemplateSpecializationType; var type = templateType.Arguments[0].Type; var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType(); var managedType = isPointerToPrimitive ? new CILType(typeof(System.IntPtr)) : type.Type; var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name : ctx.ArgName; var tmpVarName = "_tmp" + entryString; var cppTypePrinter = new CppTypePrinter(); var nativeType = type.Type.Visit(cppTypePrinter); ctx.SupportBefore.WriteLine("auto {0} = std::vector<{1}>();", tmpVarName, nativeType); ctx.SupportBefore.WriteLine("for each({0} _element in {1})", managedType, entryString); ctx.SupportBefore.WriteStartBraceIndent(); { var param = new Parameter { Name = "_element", QualifiedType = type }; var elementCtx = new MarshalContext(ctx.Context) { Parameter = param, ArgName = param.Name, }; var marshal = new CLIMarshalManagedToNativePrinter(elementCtx); type.Type.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) ctx.SupportBefore.Write(marshal.Context.SupportBefore); if (isPointerToPrimitive) ctx.SupportBefore.WriteLine("auto _marshalElement = {0}.ToPointer();", marshal.Context.Return); else ctx.SupportBefore.WriteLine("auto _marshalElement = {0};", marshal.Context.Return); ctx.SupportBefore.WriteLine("{0}.push_back(_marshalElement);", tmpVarName); } ctx.SupportBefore.WriteCloseBraceIndent(); ctx.Return.Write(tmpVarName); }
public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals) { if (!VisitType(pointer, quals)) return false; var pointee = pointer.Pointee.Desugar(); if (pointee.IsPrimitiveType(PrimitiveType.Void)) { Context.Return.Write("::System::IntPtr({0})", Context.ReturnVarName); return true; } if (CSharpTypePrinter.IsConstCharString(pointer)) { Context.Return.Write(MarshalStringToManaged(Context.ReturnVarName, pointer.Pointee.Desugar() as BuiltinType)); return true; } PrimitiveType primitive; var param = Context.Parameter; if (param != null && (param.IsOut || param.IsInOut) && pointee.IsPrimitiveType(out primitive)) { Context.Return.Write(Context.ReturnVarName); return true; } if (pointee.IsPrimitiveType(out primitive)) { var returnVarName = Context.ReturnVarName; if (quals.IsConst != Context.ReturnType.Qualifiers.IsConst) { var nativeTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase, false); var returnType = Context.ReturnType.Type.Desugar(); var constlessPointer = new PointerType() { IsDependent = pointer.IsDependent, Modifier = pointer.Modifier, QualifiedPointee = new QualifiedType(returnType.GetPointee()) }; var nativeConstlessTypeName = constlessPointer.Visit(nativeTypePrinter, new TypeQualifiers()); returnVarName = string.Format("const_cast<{0}>({1})", nativeConstlessTypeName, Context.ReturnVarName); } if (pointer.Pointee is TypedefType) { var desugaredPointer = new PointerType() { IsDependent = pointer.IsDependent, Modifier = pointer.Modifier, QualifiedPointee = new QualifiedType(pointee) }; var nativeTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var nativeTypeName = desugaredPointer.Visit(nativeTypePrinter, quals); Context.Return.Write("reinterpret_cast<{0}>({1})", nativeTypeName, returnVarName); } else Context.Return.Write(returnVarName); return true; } TypeMap typeMap = null; Context.Driver.TypeDatabase.FindTypeMap(pointee, out typeMap); Class @class; if (pointee.TryGetClass(out @class) && typeMap == null) { var instance = (pointer.IsReference) ? "&" + Context.ReturnVarName : Context.ReturnVarName; WriteClassInstance(@class, instance); return true; } return pointer.Pointee.Visit(this, quals); }
public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals) { if (!VisitType(pointer, quals)) { return(false); } var pointee = pointer.Pointee.Desugar(); if ((pointee.IsPrimitiveType(PrimitiveType.Char) || pointee.IsPrimitiveType(PrimitiveType.WideChar)) && pointer.QualifiedPointee.Qualifiers.IsConst) { Context.SupportBefore.WriteLine( "auto _{0} = clix::marshalString<clix::E_UTF8>({1});", Context.ArgName, Context.Parameter.Name); Context.Return.Write("_{0}.c_str()", Context.ArgName); return(true); } if (pointee is FunctionType) { var function = pointee as FunctionType; var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypeName = pointer.Visit(cppTypePrinter, quals); return(VisitDelegateType(function, cppTypeName)); } Enumeration @enum; if (pointee.TryGetEnum(out @enum)) { var isRef = Context.Parameter.Usage == ParameterUsage.Out || Context.Parameter.Usage == ParameterUsage.InOut; ArgumentPrefix.Write("&"); Context.Return.Write("(::{0}){1}{2}", @enum.QualifiedOriginalName, isRef ? string.Empty : "*", Context.Parameter.Name); return(true); } Class @class; if (pointee.TryGetClass(out @class) && @class.IsValueType) { if (Context.Function == null) { Context.Return.Write("&"); } return(pointee.Visit(this, quals)); } var finalPointee = pointer.GetFinalPointee(); if (finalPointee.IsPrimitiveType()) { var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypeName = pointer.Visit(cppTypePrinter, quals); Context.Return.Write("({0})", cppTypeName); Context.Return.Write(Context.Parameter.Name); return(true); } return(pointer.Pointee.Visit(this, quals)); }
public void GenerateFunctionCall(Function function, Class @class = null, Type publicRetType = null) { CheckArgumentRange(function); if (function.OperatorKind == CXXOperatorKind.EqualEqual || function.OperatorKind == CXXOperatorKind.ExclaimEqual) { WriteLine("bool {0}Null = ReferenceEquals({0}, nullptr);", function.Parameters[0].Name); WriteLine("bool {0}Null = ReferenceEquals({0}, nullptr);", function.Parameters[1].Name); WriteLine("if ({0}Null || {1}Null)", function.Parameters[0].Name, function.Parameters[1].Name); WriteLineIndent("return {0}{1}Null && {2}Null{3};", function.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : "!(", function.Parameters[0].Name, function.Parameters[1].Name, function.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : ")"); } var retType = function.ReturnType; if (publicRetType == null) { publicRetType = retType.Type; } var needsReturn = !publicRetType.IsPrimitiveType(PrimitiveType.Void); const string valueMarshalName = "_this0"; var isValueType = @class != null && @class.IsValueType; if (isValueType && !IsNativeFunctionOrStaticMethod(function)) { WriteLine("auto {0} = ::{1}();", valueMarshalName, @class.QualifiedOriginalName); var param = new Parameter { Name = "(*this)", Namespace = function.Namespace }; var ctx = new MarshalContext(Context) { MarshalVarPrefix = valueMarshalName, Parameter = param }; var marshal = new CLIMarshalManagedToNativePrinter(ctx); marshal.MarshalValueClassProperties(@class, valueMarshalName); if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) { Write(marshal.Context.Before); } } var @params = GenerateFunctionParamsMarshal(function.Parameters, function); var returnIdentifier = Helpers.ReturnIdentifier; if (needsReturn) { if (retType.Type.IsReference()) { Write("auto &{0} = ", returnIdentifier); } else { Write("auto {0} = ", returnIdentifier); } } if (function.OperatorKind == CXXOperatorKind.Conversion || function.OperatorKind == CXXOperatorKind.ExplicitConversion) { var method = function as Method; var typePrinter = new CppTypePrinter(); var typeName = method.ConversionType.Visit(typePrinter); WriteLine("({0}) {1};", typeName, @params[0].Name); } else if (function.IsOperator && function.OperatorKind != CXXOperatorKind.Subscript) { var opName = function.Name.Replace("operator", "").Trim(); switch (Operators.ClassifyOperator(function)) { case CXXOperatorArity.Unary: WriteLine("{0} {1};", opName, @params[0].Name); break; case CXXOperatorArity.Binary: WriteLine("{0} {1} {2};", @params[0].Name, opName, @params[1].Name); break; } } else { if (IsNativeFunctionOrStaticMethod(function)) { Write("::{0}(", function.QualifiedOriginalName); } else { if (isValueType) { Write("{0}.", valueMarshalName); } else if (IsNativeMethod(function)) { Write("((::{0}*)NativePtr)->", @class.QualifiedOriginalName); } Write("{0}(", function.OriginalName); } GenerateFunctionParams(@params); WriteLine(");"); } foreach (var paramInfo in @params) { var param = paramInfo.Param; if (param.Usage != ParameterUsage.Out && param.Usage != ParameterUsage.InOut) { continue; } if (param.Type.IsPointer() && !param.Type.GetFinalPointee().IsPrimitiveType()) { param.QualifiedType = new QualifiedType(param.Type.GetFinalPointee()); } var nativeVarName = paramInfo.Name; var ctx = new MarshalContext(Context) { ArgName = nativeVarName, ReturnVarName = nativeVarName, ReturnType = param.QualifiedType }; var marshal = new CLIMarshalNativeToManagedPrinter(ctx); param.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) { Write(marshal.Context.Before); } WriteLine("{0} = {1};", param.Name, marshal.Context.Return); } if (isValueType && !IsNativeFunctionOrStaticMethod(function)) { GenerateStructMarshaling(@class, valueMarshalName + "."); } if (needsReturn) { var retTypeName = retType.Visit(TypePrinter).ToString(); var isIntPtr = retTypeName.Contains("IntPtr"); if (retType.Type.IsPointer() && (isIntPtr || retTypeName.EndsWith("^", StringComparison.Ordinal))) { WriteLine("if ({0} == nullptr) return {1};", returnIdentifier, isIntPtr ? "System::IntPtr()" : "nullptr"); } var ctx = new MarshalContext(Context) { ArgName = returnIdentifier, ReturnVarName = returnIdentifier, ReturnType = retType }; var marshal = new CLIMarshalNativeToManagedPrinter(ctx); retType.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) { Write(marshal.Context.Before); } // Special case for indexer - needs to dereference if the internal // function is a pointer type and the property is not. if (retType.Type.IsPointer() && retType.Type.GetPointee().Equals(publicRetType) && publicRetType.IsPrimitiveType()) { WriteLine("return *({0});", marshal.Context.Return); } else if (retType.Type.IsReference() && publicRetType.IsReference()) { WriteLine("return ({0})({1});", publicRetType, marshal.Context.Return); } else { WriteLine("return {0};", marshal.Context.Return); } } }
public override void CLIMarshalToNative(MarshalContext ctx) { var templateType = Type as TemplateSpecializationType; var type1 = templateType.Arguments[0].Type; var type2 = templateType.Arguments[1].Type; var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name : ctx.ArgName; var tmpVarName = "_tmp" + entryString; var cppTypePrinter = new CppTypePrinter(ctx.Driver.TypeDatabase); var nativeType1 = type1.Type.Visit(cppTypePrinter); var nativeType2 = type2.Type.Visit(cppTypePrinter); ctx.SupportBefore.WriteLine("auto {0} = HashMap<{1}, {2}>();", tmpVarName, nativeType1, nativeType2); ctx.SupportBefore.WriteLine("auto _keys = {0}->Keys->GetEnumerator();", entryString); ctx.SupportBefore.WriteLine("while (_keys.MoveNext())"); ctx.SupportBefore.WriteStartBraceIndent(); { ctx.SupportBefore.WriteLine("{0} _key = _keys.Current;", type1.ToString()); ctx.SupportBefore.WriteLine("{0} _val = {1}[_key];", type2.ToString(), entryString); var param1 = new Parameter { Name = "_key", QualifiedType = type1 }; var elementCtx1 = new MarshalContext(ctx.Driver) { Parameter = param1, ArgName = param1.Name, }; var marshal1 = new CLIMarshalManagedToNativePrinter(elementCtx1); type1.Type.Visit(marshal1); if (!string.IsNullOrWhiteSpace(marshal1.Context.SupportBefore)) ctx.SupportBefore.Write(marshal1.Context.SupportBefore); ctx.SupportBefore.WriteLine("auto _marshalKey = {0};", marshal1.Context.Return); var param2 = new Parameter { Name = "_val", QualifiedType = type2 }; var elementCtx2 = new MarshalContext(ctx.Driver) { Parameter = param2, ArgName = param2.Name, }; var marshal2 = new CLIMarshalManagedToNativePrinter(elementCtx2); type2.Type.Visit(marshal2); if (!string.IsNullOrWhiteSpace(marshal2.Context.SupportBefore)) ctx.SupportBefore.Write(marshal2.Context.SupportBefore); ctx.SupportBefore.WriteLine("auto _marshalValue = {0};", marshal2.Context.Return); ctx.SupportBefore.WriteLine("{0}[_marshalKey] = _marshalValue;", tmpVarName); } ctx.SupportBefore.WriteCloseBraceIndent(); ctx.Return.Write(tmpVarName); }
public bool FindTypeMap(Type type, out TypeMap typeMap) { var typePrinter = new CppTypePrinter(this); var template = type as TemplateSpecializationType; if (template != null) return FindTypeMap(template.Template.TemplatedDecl, type, out typeMap); if (FindTypeMap(type.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } typePrinter.PrintKind = CppTypePrintKind.Qualified; if (FindTypeMap(type.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } return false; }
public bool FindTypeMap(Declaration decl, Type type, out TypeMap typeMap) { // We try to find type maps from the most qualified to less qualified // types. Example: '::std::vector', 'std::vector' and 'vector' var typePrinter = new CppTypePrinter(this) { PrintKind = CppTypePrintKind.GlobalQualified }; if (FindTypeMap(decl.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } typePrinter.PrintKind = CppTypePrintKind.Qualified; if (FindTypeMap(decl.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } typePrinter.PrintKind = CppTypePrintKind.Local; if (FindTypeMap(decl.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } return false; }
public override bool VisitFieldDecl(Field field) { if (!VisitDeclaration(field)) return false; var type = field.Type; string msg; if (!HasInvalidType(type, out msg)) return false; field.ExplicitlyIgnore(); var @class = (Class)field.Namespace; var cppTypePrinter = new CppTypePrinter(Driver.TypeDatabase); var typeName = type.Visit(cppTypePrinter); Log.Debug("Field '{0}::{1}' was ignored due to {2} type '{3}'", @class.Name, field.Name, msg, typeName); return true; }
public bool FindTypeMap(Declaration decl, Type type, out TypeMap typeMap) { // We try to find type maps from the most qualified to less qualified // types. Example: '::std::vector', 'std::vector' and 'vector' var typePrinter = new CppTypePrinter { PrintLogicalNames = true }; if (FindTypeMap(decl.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } typePrinter.PrintScopeKind = CppTypePrintScopeKind.Qualified; if (FindTypeMap(decl.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } typePrinter.PrintScopeKind = CppTypePrintScopeKind.Local; if (FindTypeMap(decl.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } var specialization = decl as ClassTemplateSpecialization; if (specialization != null && FindTypeMap(specialization.TemplatedDecl.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } var typedef = decl as TypedefDecl; return typedef != null && FindTypeMap(typedef.Type, out typeMap); }
private bool TryMatch(Function function, string docs, bool markObsolete, bool completeSignature = true) { const string memberDoc = @"(^|( --)|\n)\n([\w :*&<>,]+)?(({0}(\s*&)?::)| ){1}(const)?( \[(\w+\s*)+\])?\n(?<docs>\w.*?)(\n\s*){{1,2}}((&?\S* --)|((\n\s*){{2}}))"; const string separator = @",\s*"; StringBuilder signatureRegex = new StringBuilder(Regex.Escape(function.OriginalName)).Append(@"\s*\(\s*("); bool anyArgs = false; CppTypePrinter cppTypePrinter = new CppTypePrinter(new TypeMapDatabase()); cppTypePrinter.PrintKind = CppTypePrintKind.Local; foreach (string argType in function.Parameters.Where(p => p.Kind == ParameterKind.Regular).Select(p => p.Type.Visit(cppTypePrinter))) { if (!anyArgs) { signatureRegex.Append("?<args>"); anyArgs = true; } signatureRegex.Append(this.GetTypeRegex(argType, completeSignature)).Append(@"(\s+\w+(\s*=\s*[^,\r\n]+(\(\s*\))?)?)?"); signatureRegex.Append(separator); } if (anyArgs) { signatureRegex.Insert(signatureRegex.Length - separator.Length, '('); } else { signatureRegex.Append('('); } signatureRegex.Append(@"[\w :*&<>]+\s*=\s*[^,\r\n]+(\(\s*\))?(,\s*)?)*)\s*\)\s*"); Match match = Regex.Match(docs, string.Format(memberDoc, function.Namespace.Name, signatureRegex), RegexOptions.Singleline | RegexOptions.ExplicitCapture); if (match.Success) { function.Comment = new RawComment(); function.Comment.BriefText = match.Groups["docs"].Value; FillMissingParameterNames(function, match.Groups["args"].Value); if (markObsolete) { AddObsoleteAttribute(function); } return true; } return false; }
void GenerateGetHashCode(Class @class, Block block) { var hashcodeOverride = @class.Methods.FirstOrDefault(m => { var expansions = m.PreprocessedEntities.OfType<MacroExpansion>(); return expansions.Any(e => e.Text == "FLD_HASHCODE"); }); if (hashcodeOverride == null) return; var cppTypePrinter = new CppTypePrinter(Driver.TypeDatabase); var classCppType = @class.Visit(cppTypePrinter); block.Text.StringBuilder.Clear(); block.WriteLine("return (({0}*)NativePtr)->{1}();", classCppType, hashcodeOverride.OriginalName); }
public override void CLIMarshalToNative(MarshalContext ctx) { var templateType = Type as TemplateSpecializationType; var type = templateType.Arguments[0].Type; var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name : ctx.ArgName; var tmpVarName = "_tmp" + entryString; var cppTypePrinter = new CppTypePrinter(ctx.Driver.TypeDatabase); var nativeType = type.Type.Visit(cppTypePrinter); ctx.SupportBefore.WriteLine("auto {0} = Vector<{1}>();", tmpVarName, nativeType); ctx.SupportBefore.WriteLine("for each({0} _element in {1})", type.ToString(), entryString); ctx.SupportBefore.WriteStartBraceIndent(); { var param = new Parameter { Name = "_element", QualifiedType = type }; var elementCtx = new MarshalContext(ctx.Driver) { Parameter = param, ArgName = param.Name, }; var marshal = new CLIMarshalManagedToNativePrinter(elementCtx); type.Type.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) ctx.SupportBefore.Write(marshal.Context.SupportBefore); ctx.SupportBefore.WriteLine("auto _marshalElement = {0};", marshal.Context.Return); ctx.SupportBefore.WriteLine("{0}.Push(_marshalElement);", tmpVarName); } ctx.SupportBefore.WriteCloseBraceIndent(); ctx.Return.Write(tmpVarName); }
public void GenerateClassEvents(Class @class) { foreach (var @event in @class.Events) { if ([email protected]) continue; var cppTypePrinter = new CppTypePrinter(); var cppArgs = cppTypePrinter.VisitParameters(@event.Parameters, hasNames: true); WriteLine("private:"); PushIndent(); var delegateName = string.Format("_{0}Delegate", @event.Name); WriteLine("delegate void {0}({1});", delegateName, cppArgs); WriteLine("{0}^ {0}Instance;", delegateName); WriteLine("void _{0}Raise({1});", @event.Name, cppArgs); WriteLine("{0} _{1};", @event.Type, @event.Name); PopIndent(); WriteLine("public:"); PushIndent(); WriteLine("event {0} {1}", @event.Type, @event.Name); WriteStartBraceIndent(); WriteLine("void add({0} evt);", @event.Type); WriteLine("void remove({0} evt);", @event.Type); var cliTypePrinter = new CLITypePrinter(Driver); var cliArgs = cliTypePrinter.VisitParameters(@event.Parameters, hasNames: true); WriteLine("void raise({0});", cliArgs); WriteCloseBraceIndent(); PopIndent(); } }
public bool FindTypeMap(Type type, out TypeMap typeMap) { var typePrinter = new CppTypePrinter { PrintTypeQualifiers = false, PrintTypeModifiers = false, PrintLogicalNames = true }; var template = type as TemplateSpecializationType; if (template != null) { var specialization = template.GetClassTemplateSpecialization(); if (specialization != null && FindTypeMap(specialization, type, out typeMap)) return true; if (template.Template.TemplatedDecl != null) return FindTypeMap(template.Template.TemplatedDecl, type, out typeMap); } if (FindTypeMap(type.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } if (FindTypeMap(type.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } typePrinter.PrintScopeKind = CppTypePrintScopeKind.Qualified; if (FindTypeMap(type.Visit(typePrinter), out typeMap)) { typeMap.Type = type; return true; } var typedef = type as TypedefType; return typedef != null && FindTypeMap(typedef.Declaration, type, out typeMap); }
public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals) { if (!VisitType(pointer, quals)) return false; var pointee = pointer.Pointee.Desugar(); if ((pointee.IsPrimitiveType(PrimitiveType.Char) || pointee.IsPrimitiveType(PrimitiveType.WideChar)) && pointer.QualifiedPointee.Qualifiers.IsConst) { Context.SupportBefore.WriteLine( "auto _{0} = clix::marshalString<clix::E_UTF8>({1});", Context.ArgName, Context.Parameter.Name); Context.Return.Write("_{0}.c_str()", Context.ArgName); return true; } if (pointee is FunctionType) { var function = pointee as FunctionType; var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypeName = pointer.Visit(cppTypePrinter, quals); return VisitDelegateType(function, cppTypeName); } Class @class; if (pointee.IsTagDecl(out @class) && @class.IsValueType) { if (Context.Function == null) Context.Return.Write("&"); return pointee.Visit(this, quals); } PrimitiveType primitive; if (pointee.IsPrimitiveType(out primitive)) { var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypeName = pointer.Visit(cppTypePrinter, quals); Context.Return.Write("({0})", cppTypeName); Context.Return.Write(Context.Parameter.Name); return true; } return pointer.Pointee.Visit(this, quals); }
private ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex, Function function = null) { var paramMarshal = new ParamMarshal { Name = param.Name, Param = param }; if (param.Type is BuiltinType) { return(paramMarshal); } var argName = Generator.GeneratedIdentifier("arg") + paramIndex.ToString(CultureInfo.InvariantCulture); var isRef = param.IsOut || param.IsInOut; // Since both pointers and references to types are wrapped as CLI // tracking references when using in/out, we normalize them here to be able // to use the same code for marshaling. var paramType = param.Type; if (paramType is PointerType && isRef) { if (!paramType.IsReference()) { paramMarshal.Prefix = "&"; } paramType = (paramType as PointerType).Pointee; } var effectiveParam = new Parameter(param) { QualifiedType = new QualifiedType(paramType) }; var ctx = new MarshalContext(Context) { Parameter = effectiveParam, ParameterIndex = paramIndex, ArgName = argName, Function = function }; var marshal = new CLIMarshalManagedToNativePrinter(ctx); effectiveParam.Visit(marshal); if (string.IsNullOrEmpty(marshal.Context.Return)) { throw new Exception(string.Format("Cannot marshal argument of function '{0}'", function.QualifiedOriginalName)); } if (isRef) { var typePrinter = new CppTypePrinter(); var type = paramType.Visit(typePrinter); if (param.IsInOut) { if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) { Write(marshal.Context.Before); } WriteLine("{0} {1} = {2};", type, argName, marshal.Context.Return); } else { WriteLine("{0} {1};", type, argName); } } else { if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) { Write(marshal.Context.Before); } WriteLine("auto {0}{1} = {2};", marshal.VarPrefix, argName, marshal.Context.Return); paramMarshal.Prefix = marshal.ArgumentPrefix; } paramMarshal.Name = argName; return(paramMarshal); }
public override void CLIMarshalToNative(MarshalContext ctx) { var templateType = Type as TemplateSpecializationType; var type = templateType.Arguments[0].Type; var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType(); var managedType = isPointerToPrimitive ? new CILType(typeof(System.IntPtr)) : type.Type; var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name : ctx.ArgName; var tmpVarName = "_tmp" + entryString; var cppTypePrinter = new CppTypePrinter(); var nativeType = type.Type.Visit(cppTypePrinter); ctx.Before.WriteLine("auto {0} = std::vector<{1}>();", tmpVarName, nativeType); ctx.Before.WriteLine("for each({0} _element in {1})", managedType, entryString); ctx.Before.WriteOpenBraceAndIndent(); { var param = new Parameter { Name = "_element", QualifiedType = type }; var elementCtx = new MarshalContext(ctx.Context, ctx.Indentation) { Parameter = param, ArgName = param.Name, }; var marshal = new CLIMarshalManagedToNativePrinter(elementCtx); type.Type.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) { ctx.Before.Write(marshal.Context.Before); } if (isPointerToPrimitive) { ctx.Before.WriteLine("auto _marshalElement = {0}.ToPointer();", marshal.Context.Return); } else { ctx.Before.WriteLine("auto _marshalElement = {0};", marshal.Context.Return); } ctx.Before.WriteLine("{0}.push_back(_marshalElement);", tmpVarName); } ctx.Before.UnindentAndWriteCloseBrace(); ctx.Return.Write(tmpVarName); }
private ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex, Function function = null) { var paramMarshal = new ParamMarshal { Name = param.Name, Param = param }; if (param.Type is BuiltinType) { return(paramMarshal); } var argName = Generator.GeneratedIdentifier("arg") + paramIndex.ToString(CultureInfo.InvariantCulture); var isRef = param.IsOut || param.IsInOut; var paramType = param.Type; // Get actual type if the param type is a typedef but not a function type because function types have to be typedef. // We need to get the actual type this early before we visit any marshalling code to ensure we hit the marshalling // logic for the actual type and not the typedef. // This fixes issues where typedefs to primitive pointers are involved. FunctionType functionType; var paramTypeAsTypedef = paramType as TypedefType; if (paramTypeAsTypedef != null && !paramTypeAsTypedef.Declaration.Type.IsPointerTo(out functionType)) { paramType = param.Type.Desugar(); } // Since both pointers and references to types are wrapped as CLI // tracking references when using in/out, we normalize them here to be able // to use the same code for marshaling. if (paramType is PointerType && isRef) { if (!paramType.IsReference()) { paramMarshal.Prefix = "&"; } paramType = (paramType as PointerType).Pointee; } var effectiveParam = new Parameter(param) { QualifiedType = new QualifiedType(paramType) }; var ctx = new MarshalContext(Context, CurrentIndentation) { Parameter = effectiveParam, ParameterIndex = paramIndex, ArgName = argName, Function = function }; var marshal = new CLIMarshalManagedToNativePrinter(ctx); effectiveParam.Visit(marshal); if (string.IsNullOrEmpty(marshal.Context.Return)) { throw new Exception($"Cannot marshal argument of function '{function.QualifiedOriginalName}'"); } if (isRef) { var typePrinter = new CppTypePrinter(Context) { ResolveTypeMaps = false }; var type = paramType.Visit(typePrinter); if (param.IsInOut) { if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) { Write(marshal.Context.Before); } WriteLine("{0} {1} = {2};", type, argName, marshal.Context.Return); } else { WriteLine("{0} {1};", type, argName); } } else { if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) { Write(marshal.Context.Before); } WriteLine("auto {0}{1} = {2};", marshal.VarPrefix, argName, marshal.Context.Return); paramMarshal.Prefix = marshal.ArgumentPrefix; } paramMarshal.Name = argName; return(paramMarshal); }
private void DocumentQtProperty(Property property) { string file = GetFileForDeclarationContext(property.Namespace); if (this.documentation.ContainsKey(file)) { string docs = this.documentation[file]; CppTypePrinter cppTypePrinter = new CppTypePrinter(new TypeMapDatabase()); cppTypePrinter.PrintKind = CppTypePrintKind.Local; string type = property.Type.Visit(cppTypePrinter); Match match = Regex.Match(docs, "Property Documentation.*" + property.Name + @" : (const )?(\w+::)?" + type.Replace("*", @"\s*\*") + @"(\s+const)?\n(?<docs>.*?)\nAccess functions:", RegexOptions.Singleline | RegexOptions.ExplicitCapture); if (match.Success) { property.Comment = new RawComment(); property.Comment.BriefText = match.Groups["docs"].Value; } } }
public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals) { if (!VisitType(pointer, quals)) { return(false); } var pointee = pointer.Pointee.Desugar(); if (pointee.IsPrimitiveType(PrimitiveType.Void)) { Context.Return.Write("::System::IntPtr({0})", Context.ReturnVarName); return(true); } if (CSharpTypePrinter.IsConstCharString(pointer)) { Context.Return.Write(MarshalStringToManaged(Context.ReturnVarName, pointer.Pointee.Desugar() as BuiltinType)); return(true); } PrimitiveType primitive; var param = Context.Parameter; if (param != null && (param.IsOut || param.IsInOut) && pointee.IsPrimitiveType(out primitive)) { Context.Return.Write(Context.ReturnVarName); return(true); } if (pointee.IsPrimitiveType(out primitive)) { var returnVarName = Context.ReturnVarName; if (quals.IsConst != Context.ReturnType.Qualifiers.IsConst) { var nativeTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase, false); var returnType = Context.ReturnType.Type.Desugar(); var constlessPointer = new PointerType() { IsDependent = pointer.IsDependent, Modifier = pointer.Modifier, QualifiedPointee = new QualifiedType(returnType.GetPointee()) }; var nativeConstlessTypeName = constlessPointer.Visit(nativeTypePrinter, new TypeQualifiers()); returnVarName = string.Format("const_cast<{0}>({1})", nativeConstlessTypeName, Context.ReturnVarName); } if (pointer.Pointee is TypedefType) { var desugaredPointer = new PointerType() { IsDependent = pointer.IsDependent, Modifier = pointer.Modifier, QualifiedPointee = new QualifiedType(pointee) }; var nativeTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var nativeTypeName = desugaredPointer.Visit(nativeTypePrinter, quals); Context.Return.Write("reinterpret_cast<{0}>({1})", nativeTypeName, returnVarName); } else { Context.Return.Write(returnVarName); } return(true); } TypeMap typeMap = null; Context.Driver.TypeDatabase.FindTypeMap(pointee, out typeMap); Class @class; if (pointee.TryGetClass(out @class) && typeMap == null) { var instance = (pointer.IsReference) ? "&" + Context.ReturnVarName : Context.ReturnVarName; WriteClassInstance(@class, instance); return(true); } return(pointer.Pointee.Visit(this, quals)); }
void GenerateEquals(Class @class, Block block, Method method) { var equalsOverride = @class.Methods.FirstOrDefault(m => { var expansions = m.PreprocessedEntities.OfType<MacroExpansion>(); return expansions.Any(e => e.Text == "FLD_EQUALS"); }); if (equalsOverride == null) return; var cliTypePrinter = new CLITypePrinter(Driver); var cppTypePrinter = new CppTypePrinter(Driver.TypeDatabase); var paramCppType = equalsOverride.Parameters[0].Visit(cppTypePrinter); var classCppType = @class.Visit(cppTypePrinter); var classCliType = @class.Visit(cliTypePrinter); block.Text.StringBuilder.Clear(); block.WriteLine("if (!object) return false;"); block.WriteLine("auto obj = dynamic_cast<{0}>({1});", classCliType, method.Parameters[0].Name); block.NewLine(); block.WriteLine("if (!obj) return false;"); block.WriteLine("auto param = ({0})obj->NativePtr;", paramCppType); block.WriteLine("return (({0}*)NativePtr)->{1}(param);", classCppType, equalsOverride.OriginalName); }