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); }
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); }
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)); }
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())); }
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())); }
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); }
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())); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }