Example #1
0
        private void MarshalVariableArray(Type arrayType)
        {
            if (arrayType.IsPrimitiveType())
            {
                Context.Return.Write(Context.Parameter.Name);
                return;
            }

            var intermediateArray     = $"__{Context.Parameter.Name}";
            var intermediateArrayType = typePrinter.PrintNative(arrayType);
            var intPtrZero            = $"{CSharpTypePrinter.IntPtrType}.Zero";

            Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};");

            Context.Before.WriteLine($"if (ReferenceEquals({Context.Parameter.Name}, null))");
            if (arrayType.IsAddress())
            {
                Context.Before.WriteLineIndent($"{intermediateArray} = new[] {{ {intPtrZero} }};");
            }
            else
            {
                Context.Before.WriteLineIndent($"{intermediateArray} = new[] {{ new {intermediateArrayType}() }};");
            }
            Context.Before.WriteLine("else");

            Context.Before.WriteStartBraceIndent();
            Context.Before.WriteLine($@"{intermediateArray} = new {
                intermediateArrayType}[{Context.Parameter.Name}.Length];");
            Context.Before.WriteLine($"for (int i = 0; i < {intermediateArray}.Length; i++)");

            Context.Before.WriteStartBraceIndent();
            const string element = "__element";

            Context.Before.WriteLine($"var {element} = {Context.Parameter.Name}[i];");
            if (arrayType.IsAddress())
            {
                Context.Before.WriteLine($@"{intermediateArray}[i] = ReferenceEquals({
                    element}, null) ? {intPtrZero} : {element}.{Helpers.InstanceIdentifier};");
            }
            else
            {
                Context.Before.WriteLine($@"{intermediateArray}[i] = ReferenceEquals({
                    element}, null) ? new {intermediateArrayType}() : *({
                    intermediateArrayType}*) {element}.{Helpers.InstanceIdentifier};");
            }
            Context.Before.WriteCloseBraceIndent();

            Context.Before.WriteCloseBraceIndent();

            Context.Return.Write(intermediateArray);
        }
Example #2
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);

            if (returnType.IsAddress())
            {
                Context.Return.Write(HandleReturnedPointer(@class, qualifiedClass.Type));
            }
            else
            {
                Context.Return.Write($"{qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName})");
            }

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

            if (finalType.TryGetClass(out returnedClass) && returnedClass.IsDependent)
            {
                Context.Return.Write($" as {returnType.Visit(typePrinter)}");
            }
            return(true);
        }
Example #3
0
        private void MarshalRefClass(Class @class)
        {
            var method = Context.Function as Method;

            if (method != null &&
                method.Conversion == MethodConversionKind.FunctionToInstanceMethod &&
                Context.ParameterIndex == 0)
            {
                Context.Return.Write("{0}", Helpers.InstanceIdentifier);
                return;
            }

            string param = Context.Parameter.Name;
            Type   type  = Context.Parameter.Type.Desugar();

            if (type.IsAddress())
            {
                Class decl;
                if (type.TryGetClass(out decl) && decl.IsValueType)
                {
                    Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier);
                }
                else
                {
                    if (type.IsPointer())
                    {
                        Context.Return.Write("{0}{1}.{2}",
                                             method != null && method.OperatorKind == CXXOperatorKind.EqualEqual
                                ? string.Empty
                                : string.Format("ReferenceEquals({0}, null) ? global::System.IntPtr.Zero : ", param),
                                             param, Helpers.InstanceIdentifier, type);
                    }
                    else
                    {
                        if (method == null ||
                            // redundant for comparison operators, they are handled in a special way
                            (method.OperatorKind != CXXOperatorKind.EqualEqual &&
                             method.OperatorKind != CXXOperatorKind.ExclaimEqual))
                        {
                            Context.SupportBefore.WriteLine("if (ReferenceEquals({0}, null))", param);
                            Context.SupportBefore.WriteLineIndent(
                                "throw new global::System.ArgumentNullException(\"{0}\", " +
                                "\"Cannot be null because it is a C++ reference (&).\");",
                                param);
                        }
                        Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier);
                    }
                }
                return;
            }

            var realClass           = @class.OriginalClass ?? @class;
            var qualifiedIdentifier = realClass.Visit(this.typePrinter);

            Context.Return.Write(
                "ReferenceEquals({0}, null) ? new {1}.Internal{3}() : *({1}.Internal{3}*) ({0}.{2})", param,
                qualifiedIdentifier, Helpers.InstanceIdentifier, Helpers.GetSuffixForInternal(@class));
        }
Example #4
0
        public override string CSharpSignature(CSharpTypePrinterContext ctx)
        {
            if (ctx.CSharpKind == CSharpTypePrinterContextKind.Native)
            {
                return(Type.IsAddress() ? "QList.Internal*" : "QList.Internal");
            }

            return(string.Format("System.Collections.Generic.{0}<{1}>",
                                 ctx.CSharpKind == CSharpTypePrinterContextKind.DefaultExpression ? "List" : "IList",
                                 ctx.GetTemplateParameterList()));
        }
Example #5
0
        public override string CSharpSignature(CSharpTypePrinterContext ctx)
        {
            if (ctx.CSharpKind == CSharpTypePrinterContextKind.Native)
            {
                return(string.Format("QList.{0}{1}", Helpers.InternalStruct,
                                     Type.IsAddress() ? "*" : string.Empty));
            }

            return(string.Format("System.Collections.Generic.{0}<{1}>",
                                 ctx.MarshalKind == CSharpMarshalKind.DefaultExpression ? "List" : "IList",
                                 ctx.GetTemplateParameterList()));
        }
Example #6
0
        private void MarshalArray(ArrayType array)
        {
            Type arrayType = array.Type.Desugar();

            if (arrayType.IsPrimitiveType() ||
                arrayType.IsPointerToPrimitiveType() ||
                Context.MarshalKind != MarshalKind.GenericDelegate)
            {
                Context.Return.Write(Context.ReturnVarName);
                return;
            }

            var intermediateArray     = Generator.GeneratedIdentifier(Context.ReturnVarName);
            var intermediateArrayType = arrayType.Visit(typePrinter);

            Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};");

            Context.Before.WriteLine($"if (ReferenceEquals({Context.ReturnVarName}, null))");
            Context.Before.WriteLineIndent($"{intermediateArray} = null;");
            Context.Before.WriteLine("else");

            Context.Before.WriteStartBraceIndent();
            Context.Before.WriteLine($@"{intermediateArray} = new {
                intermediateArrayType}[{Context.ReturnVarName}.Length];");
            Context.Before.WriteLine($"for (int i = 0; i < {intermediateArray}.Length; i++)");

            if (arrayType.IsAddress())
            {
                Context.Before.WriteStartBraceIndent();
                string element = Generator.GeneratedIdentifier("element");
                Context.Before.WriteLine($"var {element} = {Context.ReturnVarName}[i];");
                var intPtrZero = $"{CSharpTypePrinter.IntPtrType}.Zero";
                Context.Before.WriteLine($@"{intermediateArray}[i] = {element} == {
                    intPtrZero} ? null : {intermediateArrayType}.{
                    Helpers.CreateInstanceIdentifier}({element});");
                Context.Before.WriteCloseBraceIndent();
            }
            else
            {
                Context.Before.WriteLineIndent($@"{intermediateArray}[i] = {
                    intermediateArrayType}.{Helpers.CreateInstanceIdentifier}({
                    Context.ReturnVarName}[i]);");
            }

            Context.Before.WriteCloseBraceIndent();

            Context.Return.Write(intermediateArray);
        }
Example #7
0
        public override string CSharpSignature(TypePrinterContext ctx)
        {
            if (ctx.Kind == TypePrinterContextKind.Native)
            {
                var type           = (TemplateSpecializationType)ctx.Type.Desugar();
                var specialization = type.GetClassTemplateSpecialization();
                var typePrinter    = new CSharpTypePrinter(null);
                typePrinter.PushContext(TypePrinterContextKind.Native);
                return(string.Format($"{specialization.Visit(typePrinter)}{(Type.IsAddress() ? "*" : string.Empty)}", specialization.Visit(typePrinter),
                                     Type.IsAddress() ? "*" : string.Empty));
            }

            return(string.Format("System.Collections.Generic.{0}<{1}>",
                                 ctx.MarshalKind == MarshalKind.DefaultExpression ? "List" : "IList",
                                 ctx.GetTemplateParameterList()));
        }
Example #8
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);

            if (returnType.IsAddress())
            {
                Context.Return.Write(HandleReturnedPointer(@class, qualifiedClass.Type));
            }
            else
            {
                Context.Return.Write("{0}.{1}({2})", qualifiedClass, Helpers.CreateInstanceIdentifier, Context.ReturnVarName);
            }

            return(true);
        }
Example #9
0
        public override bool VisitClassDecl(Class @class)
        {
            var instance = Context.ReturnVarName;

            @class = @class.OriginalClass ?? @class;
            Type returnType = Context.ReturnType.Type.Desugar();

            var type = QualifiedIdentifier(@class) +
                       (Context.Driver.Options.GenerateAbstractImpls && @class.IsAbstract ?
                        "Internal" : "");

            if (returnType.IsAddress())
            {
                var ret = Generator.GeneratedIdentifier("result") + Context.ParameterIndex;
                Context.SupportBefore.WriteLine("{0} {1};", type, ret);
                Context.SupportBefore.WriteLine("if ({0} == IntPtr.Zero) {1} = {2};", instance, ret,
                                                @class.IsRefType ? "null" : string.Format("new {0}()", type));
                var dtor = @class.Destructors.FirstOrDefault();
                var map  = @class.IsRefType && dtor != null && dtor.IsVirtual;
                if (map)
                {
                    Context.SupportBefore.WriteLine(
                        "else if (CppSharp.Runtime.Helpers.NativeToManagedMap.ContainsKey({0}))", instance);
                    Context.SupportBefore.WriteLineIndent("{0} = ({1}) CppSharp.Runtime.Helpers.NativeToManagedMap[{2}];",
                                                          ret, type, instance);
                    Context.SupportBefore.WriteLine("else CppSharp.Runtime.Helpers.NativeToManagedMap[{3}] = {0} = {1}.{2}({3});", ret, type,
                                                    Helpers.CreateInstanceIdentifier, instance);
                }
                else
                {
                    Context.SupportBefore.WriteLine("else {0} = {1}.{2}({3});", ret, type,
                                                    Helpers.CreateInstanceIdentifier, instance);
                }
                Context.Return.Write(ret);
            }
            else
            {
                Context.Return.Write("{0}.{1}({2})", type, Helpers.CreateInstanceIdentifier, instance);
            }

            return(true);
        }
Example #10
0
        private void MarshalRefClass(Class @class)
        {
            var method = Context.Function as Method;

            if (method != null &&
                method.Conversion == MethodConversionKind.FunctionToInstanceMethod &&
                Context.ParameterIndex == 0)
            {
                Context.Return.Write("{0}", Helpers.InstanceIdentifier);
                return;
            }

            string param = Context.Parameter.Name;
            Type   type  = Context.Parameter.Type.Desugar();

            if (type.IsAddress())
            {
                Class decl;
                if (type.TryGetClass(out decl) && decl.IsValueType)
                {
                    Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier);
                }
                else
                {
                    Context.Return.Write("{0}{1}.{2}",
                                         method != null && method.OperatorKind == CXXOperatorKind.EqualEqual
                            ? string.Empty
                            : string.Format("ReferenceEquals({0}, null) ? global::System.IntPtr.Zero : ", param),
                                         param,
                                         Helpers.InstanceIdentifier, type);
                }
                return;
            }

            var qualifiedIdentifier = CSharpMarshalNativeToManagedPrinter.QualifiedIdentifier(
                @class.OriginalClass ?? @class);

            Context.Return.Write(
                "ReferenceEquals({0}, null) ? new {1}.Internal() : *({1}.Internal*) ({0}.{2})", param,
                qualifiedIdentifier, Helpers.InstanceIdentifier);
        }
Example #11
0
        private void MarshalRefClass(Class @class)
        {
            var method = Context.Function as Method;

            if (method != null &&
                method.Conversion == MethodConversionKind.FunctionToInstanceMethod &&
                Context.ParameterIndex == 0)
            {
                Context.Return.Write("{0}", Helpers.InstanceIdentifier);
                return;
            }

            string param = Helpers.SafeIdentifier(Context.Parameter.Name);
            Type   type  = Context.Parameter.Type.Desugar();

            if (type.IsAddress())
            {
                Class decl;
                if (type.IsTagDecl(out decl) && decl.IsValueType)
                {
                    Context.Return.Write("{0}.{1}", param, Helpers.InstanceIdentifier);
                }
                else
                {
                    Context.Return.Write("{0} == ({2}) null ? global::System.IntPtr.Zero : {0}.{1}", param,
                                         Helpers.InstanceIdentifier, type);
                }
                return;
            }

            var qualifiedIdentifier = CSharpMarshalNativeToManagedPrinter.QualifiedIdentifier(
                @class.OriginalClass ?? @class);

            Context.Return.Write(
                "{1} == ({0}) null ? new {0}.Internal() : *({0}.Internal*) ({1}.{2})", qualifiedIdentifier,
                param, Helpers.InstanceIdentifier);
        }
Example #12
0
        public override bool VisitClassDecl(Class @class)
        {
            var instance = Context.ReturnVarName;

            @class = @class.OriginalClass ?? @class;
            Type returnType = Context.ReturnType.Type.Desugar();

            var type = QualifiedIdentifier(@class) +
                       (Context.Driver.Options.GenerateAbstractImpls && @class.IsAbstract ?
                        "Internal" : "");

            if (returnType.IsAddress())
            {
                Context.Return.Write("({0} == IntPtr.Zero) ? {1} : {2}.{3}({0})", instance,
                                     @class.IsRefType ? "null" : string.Format("new {0}()", type),
                                     type, Helpers.CreateInstanceIdentifier);
            }
            else
            {
                Context.Return.Write("{0}.{1}({2})", type, Helpers.CreateInstanceIdentifier, instance);
            }

            return(true);
        }
Example #13
0
        private void MarshalRefClass(Class @class)
        {
            var method = Context.Function as Method;

            if (method != null &&
                method.Conversion == MethodConversionKind.FunctionToInstanceMethod &&
                Context.ParameterIndex == 0)
            {
                Context.Return.Write("{0}", Helpers.InstanceIdentifier);
                return;
            }

            string param = Context.Parameter.Name;
            Type   type  = Context.Parameter.Type.Desugar(resolveTemplateSubstitution: false);
            string paramInstance;
            Class  @interface;
            var    finalType    = type.GetFinalPointee() ?? type;
            var    templateType = finalType as TemplateParameterSubstitutionType;

            type = Context.Parameter.Type.Desugar();
            if (finalType.TryGetClass(out @interface) &&
                @interface.IsInterface)
            {
                paramInstance = $"{param}.__PointerTo{@interface.OriginalClass.Name}";
            }
            else
            {
                paramInstance = $@"{
                    (templateType != null ? $"(({@class.Visit(typePrinter)}) (object) " : string.Empty)}{
                    param}{(templateType != null ? ")" : string.Empty)
                    }.{Helpers.InstanceIdentifier}";
            }
            if (type.IsAddress())
            {
                Class decl;
                if (type.TryGetClass(out decl) && decl.IsValueType)
                {
                    Context.Return.Write(paramInstance);
                }
                else
                {
                    if (type.IsPointer())
                    {
                        Context.Return.Write("{0}{1}",
                                             method != null && method.OperatorKind == CXXOperatorKind.EqualEqual
                                ? string.Empty
                                : $"ReferenceEquals({param}, null) ? global::System.IntPtr.Zero : ",
                                             paramInstance);
                    }
                    else
                    {
                        if (method == null ||
                            // redundant for comparison operators, they are handled in a special way
                            (method.OperatorKind != CXXOperatorKind.EqualEqual &&
                             method.OperatorKind != CXXOperatorKind.ExclaimEqual))
                        {
                            Context.Before.WriteLine("if (ReferenceEquals({0}, null))", param);
                            Context.Before.WriteLineIndent(
                                "throw new global::System.ArgumentNullException(\"{0}\", " +
                                "\"Cannot be null because it is a C++ reference (&).\");",
                                param);
                        }
                        Context.Return.Write(paramInstance);
                    }
                }
                return;
            }

            var realClass           = @class.OriginalClass ?? @class;
            var qualifiedIdentifier = typePrinter.PrintNative(realClass);

            Context.Return.Write(
                "ReferenceEquals({0}, null) ? new {1}() : *({1}*) {2}",
                param, qualifiedIdentifier, paramInstance);
        }
Example #14
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);
        }