public CSharpTypePrinterResult VisitArrayType(ArrayType array, TypeQualifiers quals) { if (ContextKind == CSharpTypePrinterContextKind.Native && array.SizeType == ArrayType.ArraySize.Constant) { Type arrayType = array.Type.Desugar(); PrimitiveType primitiveType; if (arrayType.IsPointerToPrimitiveType(out primitiveType) && !(arrayType is FunctionType)) { if (primitiveType == PrimitiveType.Void) { return("void**"); } return(string.Format("{0}*", array.Type.Visit(this, quals))); } Class @class; if (arrayType.TryGetClass(out @class)) { return(new CSharpTypePrinterResult() { Type = "fixed byte", NameSuffix = string.Format("[{0}]", array.Size * @class.Layout.Size) }); } var arrayElemType = array.Type.Visit(this, quals).ToString(); // C# does not support fixed arrays of machine pointer type (void* or IntPtr). // In that case, replace it by a pointer to an integer type of the same size. if (arrayElemType == IntPtrType) { arrayElemType = driver.TargetInfo.PointerWidth == 64 ? "long" : "int"; } // Do not write the fixed keyword multiple times for nested array types var fixedKeyword = array.Type is ArrayType ? string.Empty : "fixed "; return(new CSharpTypePrinterResult() { Type = string.Format("{0}{1}", fixedKeyword, arrayElemType), NameSuffix = string.Format("[{0}]", array.Size) }); } // const char* and const char[] are the same so we can use a string if (array.SizeType == ArrayType.ArraySize.Incomplete && array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) && array.QualifiedType.Qualifiers.IsConst) { return("string"); } return(string.Format("{0}[]", array.Type.Visit(this))); // C# only supports fixed arrays in unsafe sections // and they are constrained to a set of built-in types. }
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 CSharpTypePrinterResult VisitArrayType(ArrayType array, TypeQualifiers quals) { if (ContextKind == CSharpTypePrinterContextKind.Native && array.SizeType == ArrayType.ArraySize.Constant) { Type arrayType = array.Type.Desugar(); PrimitiveType primitiveType; if (arrayType.IsPointerToPrimitiveType(out primitiveType)) { if (primitiveType == PrimitiveType.Void) { return("void**"); } return(string.Format("{0}*", array.Type.Visit(this, quals))); } Class @class; if (arrayType.TryGetClass(out @class)) { return(new CSharpTypePrinterResult() { Type = "fixed byte", NameSuffix = string.Format("[{0}]", array.Size * @class.Layout.Size) }); } // Do not write the fixed keyword multiple times for nested array types var fixedKeyword = array.Type is ArrayType ? string.Empty : "fixed "; return(new CSharpTypePrinterResult() { Type = string.Format("{0}{1}", fixedKeyword, array.Type.Visit(this, quals)), NameSuffix = string.Format("[{0}]", array.Size) }); } // const char* and const char[] are the same so we can use a string if (array.SizeType == ArrayType.ArraySize.Incomplete && array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) && array.QualifiedType.Qualifiers.IsConst) { return("string"); } return(string.Format("{0}[]", array.Type.Visit(this))); // C# only supports fixed arrays in unsafe sections // and they are constrained to a set of built-in types. }
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); }
public override TypePrinterResult VisitArrayType(ArrayType array, TypeQualifiers quals) { Type arrayType = array.Type.Desugar(); if (ContextKind == TypePrinterContextKind.Native && array.SizeType == ArrayType.ArraySize.Constant) { PrimitiveType primitiveType; if ((arrayType.IsPointerToPrimitiveType(out primitiveType) && !(arrayType is FunctionType)) || (arrayType.IsPrimitiveType() && MarshalKind != MarshalKind.NativeField)) { if (primitiveType == PrimitiveType.Void) { return("void*"); } return(string.Format("{0}", array.Type.Visit(this, quals))); } if (Parameter != null) { return(string.Format("global::System.IntPtr")); } Enumeration @enum; if (arrayType.TryGetEnum(out @enum)) { return(new TypePrinterResult { Type = string.Format("fixed {0}", @enum.BuiltinType), NameSuffix = string.Format("[{0}]", array.Size) }); } Class @class; if (arrayType.TryGetClass(out @class)) { return(new TypePrinterResult { Type = "fixed byte", NameSuffix = string.Format("[{0}]", array.Size * @class.Layout.Size) }); } var arrayElemType = array.Type.Visit(this, quals).ToString(); // C# does not support fixed arrays of machine pointer type (void* or IntPtr). // In that case, replace it by a pointer to an integer type of the same size. if (arrayElemType == IntPtrType) { arrayElemType = Context.TargetInfo.PointerWidth == 64 ? "long" : "int"; } // Do not write the fixed keyword multiple times for nested array types var fixedKeyword = array.Type is ArrayType ? string.Empty : "fixed "; return(new TypePrinterResult { Type = string.Format("{0}{1}", fixedKeyword, arrayElemType), NameSuffix = string.Format("[{0}]", array.Size) }); } // const char* and const char[] are the same so we can use a string if (array.SizeType == ArrayType.ArraySize.Incomplete && arrayType.IsPrimitiveType(PrimitiveType.Char) && array.QualifiedType.Qualifiers.IsConst) { return("string"); } if (arrayType.IsPointerToPrimitiveType(PrimitiveType.Char)) { return("char**"); } return(string.Format("{0}{1}", array.Type.Visit(this), array.SizeType == ArrayType.ArraySize.Constant ? "[]" : (ContextKind == TypePrinterContextKind.Managed ? "*" : string.Empty))); // C# only supports fixed arrays in unsafe sections // and they are constrained to a set of built-in types. }
public override TypePrinterResult VisitArrayType(ArrayType array, TypeQualifiers quals) { Type arrayType = array.Type.Desugar(); if ((MarshalKind == MarshalKind.NativeField || (ContextKind == TypePrinterContextKind.Native && MarshalKind == MarshalKind.ReturnVariableArray)) && array.SizeType == ArrayType.ArraySize.Constant) { if (array.Size == 0) { var pointer = new PointerType(array.QualifiedType); return(pointer.Visit(this)); } PrimitiveType primitiveType; if ((arrayType.IsPointerToPrimitiveType(out primitiveType) && !(arrayType is FunctionType)) || (arrayType.IsPrimitiveType() && MarshalKind != MarshalKind.NativeField)) { if (primitiveType == PrimitiveType.Void) { return("void*"); } return(array.QualifiedType.Visit(this)); } if (Parameter != null) { return(IntPtrType); } Enumeration @enum; if (arrayType.TryGetEnum(out @enum)) { return(new TypePrinterResult { Type = $"fixed {@enum.BuiltinType}", NameSuffix = $"[{array.Size}]" }); } Class @class; if (arrayType.TryGetClass(out @class)) { return(new TypePrinterResult { Type = "fixed byte", NameSuffix = $"[{array.Size * @class.Layout.Size}]" }); } var arrayElemType = array.QualifiedType.Visit(this).ToString(); // C# does not support fixed arrays of machine pointer type (void* or IntPtr). // In that case, replace it by a pointer to an integer type of the same size. if (arrayElemType == IntPtrType) { arrayElemType = Context.TargetInfo.PointerWidth == 64 ? "long" : "int"; } // Do not write the fixed keyword multiple times for nested array types var fixedKeyword = arrayType is ArrayType ? string.Empty : "fixed "; return(new TypePrinterResult { Type = $"{fixedKeyword}{arrayElemType}", NameSuffix = $"[{array.Size}]" }); } // const char* and const char[] are the same so we can use a string if (array.SizeType == ArrayType.ArraySize.Incomplete && arrayType.IsPrimitiveType(PrimitiveType.Char) && array.QualifiedType.Qualifiers.IsConst) { return("string"); } if (arrayType.IsPointerToPrimitiveType(PrimitiveType.Char)) { var prefix = ContextKind == TypePrinterContextKind.Managed ? string.Empty : "[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] "; return($"{prefix}string[]"); } var arraySuffix = array.SizeType != ArrayType.ArraySize.Constant && MarshalKind == MarshalKind.ReturnVariableArray ? (ContextKind == TypePrinterContextKind.Managed && arrayType.IsPrimitiveType() ? "*" : string.Empty) : "[]"; return($"{arrayType.Visit(this)}{arraySuffix}"); }
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); }