Beispiel #1
0
        public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
        {
            if (!VisitType(pointer, quals))
            {
                return(false);
            }

            var param      = Context.Parameter;
            var isRefParam = param != null && (param.IsInOut || param.IsOut);

            var pointee = pointer.Pointee.Desugar();

            if (pointee.IsConstCharString())
            {
                if (param.IsOut)
                {
                    MarshalString(pointee);
                    Context.Return.Write("IntPtr.Zero");
                    Context.ArgumentPrefix.Write("&");
                    return(true);
                }
                if (param.IsInOut)
                {
                    MarshalString(pointee);
                    pointer.QualifiedPointee.Visit(this);
                    Context.ArgumentPrefix.Write("&");
                    return(true);
                }
                if (pointer.IsReference)
                {
                    Context.Return.Write($@"({typePrinter.PrintNative(
                        pointee.GetQualifiedPointee())}*) ");
                    pointer.QualifiedPointee.Visit(this);
                    Context.ArgumentPrefix.Write("&");
                    return(true);
                }
            }

            var finalPointee = (pointee.GetFinalPointee() ?? pointee).Desugar();

            if (finalPointee.IsPrimitiveType(out PrimitiveType primitive) ||
                finalPointee.IsEnumType())
            {
                if (isRefParam)
                {
                    var local = Generator.GeneratedIdentifier($@"{
                        param.Name}{Context.ParameterIndex}");
                    Context.Before.WriteLine($@"fixed ({
                        pointer.Visit(typePrinter)} {local} = &{param.Name})");
                    Context.HasCodeBlock = true;
                    Context.Before.WriteOpenBraceAndIndent();
                    Context.Return.Write(local);
                    return(true);
                }

                if (Context.Context.Options.MarshalCharAsManagedChar &&
                    primitive == PrimitiveType.Char)
                {
                    Context.Return.Write($"({typePrinter.PrintNative(pointer)}) ");
                    Context.Return.Write(param.Name);
                    return(true);
                }

                pointer.QualifiedPointee.Visit(this);

                if (Context.Parameter.IsIndirect)
                {
                    Context.ArgumentPrefix.Write("&");
                }

                bool isVoid = primitive == PrimitiveType.Void &&
                              pointee.IsAddress() && pointer.IsReference();
                if (pointer.Pointee.Desugar(false) is TemplateParameterSubstitutionType ||
                    isVoid)
                {
                    var    local = Generator.GeneratedIdentifier($@"{
                        param.Name}{Context.ParameterIndex}");
                    string cast  = isVoid ? $@"({pointee.Visit(
                        new CppTypePrinter { PrintTypeQualifiers = false })}) " : string.Empty;
                    Context.Before.WriteLine($"var {local} = {cast}{Context.Return};");
                    Context.Return.StringBuilder.Clear();
                    Context.Return.Write(local);
                }
                if (new QualifiedType(pointer, quals).IsConstRefToPrimitive())
                {
                    Context.Return.StringBuilder.Insert(0, '&');
                }

                return(true);
            }

            if (pointee.TryGetClass(out Class @class) && @class.IsValueType)
            {
                if (Context.Parameter.Usage == ParameterUsage.Out)
                {
                    var qualifiedIdentifier = (@class.OriginalClass ?? @class).Visit(typePrinter);
                    Context.Before.WriteLine("var {0} = new {1}.{2}();",
                                             Generator.GeneratedIdentifier(Context.ArgName), qualifiedIdentifier,
                                             Helpers.InternalStruct);
                }
                else
                {
                    Context.Before.WriteLine("var {0} = {1}.{2};",
                                             Generator.GeneratedIdentifier(Context.ArgName),
                                             Context.Parameter.Name,
                                             Helpers.InstanceIdentifier);
                }

                Context.Return.Write("new global::System.IntPtr(&{0})",
                                     Generator.GeneratedIdentifier(Context.ArgName));
                return(true);
            }

            return(pointer.QualifiedPointee.Visit(this));
        }