示例#1
0
        public override bool VisitClassDecl(Class @class)
        {
            var  originalClass = @class.OriginalClass ?? @class;
            Type returnType    = Context.ReturnType.Type.Desugar();

            // if the class is an abstract impl, use the original for the object map
            var qualifiedClass = originalClass.Visit(typePrinter);

            var   finalType = (returnType.GetFinalPointee() ?? returnType).Desugar();
            Class returnedClass;

            if (finalType.TryGetClass(out returnedClass) && returnedClass.IsDependent)
            {
                Context.Return.Write($"({returnType.Visit(typePrinter)}) (object) ");
            }

            // these two aren't the same for members of templates
            if (Context.Function?.OriginalReturnType.Type.Desugar().IsAddress() == true ||
                returnType.IsAddress())
            {
                Context.Return.Write(HandleReturnedPointer(@class, qualifiedClass));
            }
            else
            {
                if (Context.MarshalKind == MarshalKind.NativeField ||
                    Context.MarshalKind == MarshalKind.Variable ||
                    Context.MarshalKind == MarshalKind.ReturnVariableArray ||
                    !originalClass.HasNonTrivialDestructor)
                {
                    Context.Return.Write($"{qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName})");
                }
                else
                {
                    Context.Before.WriteLine($@"var __{Context.ReturnVarName} = {
                        qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName});");
                    Method dtor = originalClass.Destructors.First();
                    if (dtor.IsVirtual)
                    {
                        var i           = VTables.GetVTableIndex(dtor);
                        int vtableIndex = 0;
                        if (Context.Context.ParserOptions.IsMicrosoftAbi)
                        {
                            vtableIndex = @class.Layout.VFTables.IndexOf(@class.Layout.VFTables.First(
                                                                             v => v.Layout.Components.Any(c => c.Method == dtor)));
                        }
                        string instance = $"new {typePrinter.IntPtrType}(&{Context.ReturnVarName})";
                        Context.Before.WriteLine($@"var __vtables = new IntPtr[] {{ {
                            string.Join(", ", originalClass.Layout.VTablePointers.Select(
                                x => $"*({typePrinter.IntPtrType}*) ({instance} + {x.Offset})"))} }};");
                        Context.Before.WriteLine($@"var __slot = *({typePrinter.IntPtrType}*) (__vtables[{
                            vtableIndex}] + {i} * sizeof({typePrinter.IntPtrType}));");
                        Context.Before.Write($"Marshal.GetDelegateForFunctionPointer<{dtor.FunctionType}>(__slot)({instance}");
                        if (dtor.GatherInternalParams(Context.Context.ParserOptions.IsItaniumLikeAbi).Count > 1)
                        {
                            Context.Before.Write(", 0");
                        }
                        Context.Before.WriteLine(");");
                    }
                    else
                    {
                        string suffix         = string.Empty;
                        var    specialization = @class as ClassTemplateSpecialization;
                        if (specialization != null)
                        {
                            suffix = Helpers.GetSuffixFor(specialization);
                        }
                        Context.Before.WriteLine($@"{typePrinter.PrintNative(originalClass)}.dtor{
                            suffix}(new {typePrinter.IntPtrType}(&{Context.ReturnVarName}));");
                    }
                    Context.Return.Write($"__{Context.ReturnVarName}");
                }
            }

            return(true);
        }