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. }
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))); } // 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) }); } 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 static bool CheckForDefaultPointer(Type desugared, Parameter parameter) { if (desugared.IsPointer()) { // IntPtr.Zero is not a constant parameter.DefaultArgument.String = desugared.IsPointerToPrimitiveType(PrimitiveType.Void) ? "new global::System.IntPtr()" : "null"; return(true); } return(false); }
private static bool CheckForDefaultPointer(Type desugared, Parameter parameter) { if (desugared.IsPointer()) { // IntPtr.Zero is not a constant parameter.DefaultArgument.String = desugared.IsPointerToPrimitiveType(PrimitiveType.Void) ? "new global::System.IntPtr()" : "null"; return true; } return false; }
private static void WriteTemplateSpecializationCheck(CSharpSources gen, Class @class, ClassTemplateSpecialization specialization) { gen.WriteLine("if ({0})", string.Join(" && ", Enumerable.Range(0, @class.TemplateParameters.Count).Select( i => { CppSharp.AST.Type type = specialization.Arguments[i].Type.Type; return(type.IsPointerToPrimitiveType() && !type.IsConstCharString() ? $"__{@class.TemplateParameters[i].Name}.FullName == \"System.IntPtr\"" : $"__{@class.TemplateParameters[i].Name}.IsAssignableFrom(typeof({type}))"); }))); }
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 bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals) { Type returnType = Context.ReturnType.Type.Desugar(); Type finalType = (returnType.GetFinalPointee() ?? returnType).Desugar(); if (finalType.IsDependent) { Context.Return.Write($"({param.ReplacedParameter.Parameter.Name}) (object) "); } Type replacement = param.Replacement.Type.Desugar(); if (replacement.IsPointerToPrimitiveType() && !replacement.IsConstCharString()) { Context.Return.Write($"({typePrinter.IntPtrType}) "); } return(base.VisitTemplateParameterSubstitutionType(param, quals)); }
private void MarshalVariableArray(Type arrayType) { if (arrayType.IsPrimitiveType() || arrayType.IsPointerToPrimitiveType(PrimitiveType.Char)) { Context.Return.Write(Context.Parameter.Name); return; } var intermediateArray = $"__{Context.Parameter.Name}"; var intermediateArrayType = typePrinter.PrintNative(arrayType); Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};"); Context.Before.WriteLine($"if (ReferenceEquals({Context.Parameter.Name}, null))"); Context.Before.WriteLineIndent($"{intermediateArray} = null;"); 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()) { var intPtrZero = $"{CSharpTypePrinter.IntPtrType}.Zero"; 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 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 UnwrapInfo?GetUnwrapInfo(ArrayType arrayType, Type typeInArray) { long unwrapCount; Type unwrapType; // in bits long unwrapTypeWidth; if (typeInArray.IsPointerToPrimitiveType()) { // need to unwrap if field is array of pointer to primitive type // int* A[N] // becomes // int* A_0; // int* A_N; // unwrap to multiple pointer fields unwrapType = new PointerType { QualifiedPointee = ((PointerType)typeInArray).QualifiedPointee }; unwrapCount = arrayType.Size; // TODO: get type width from driver TargetInfo! unwrapTypeWidth = 0; } else if (typeInArray.IsPointerToArrayType()) { // need to unwrap if field is array of pointer to array // A (*int[N])[M] // becomes // int** X_0; // int** X_M; var innerArray = (ArrayType)((PointerType)typeInArray).Pointee; unwrapType = new PointerType { QualifiedPointee = new QualifiedType(new PointerType { QualifiedPointee = new QualifiedType(innerArray.Type) }) }; unwrapCount = arrayType.Size; unwrapTypeWidth = Driver.TargetInfo.PointerWidth; } else if (typeInArray is ArrayType) { // need to unwrap if field is array of array // int A[N][M] // becomes // int A_0[M]; // int A_N[M]; Type innerArray = ((ArrayType)(typeInArray)).Type; unwrapType = new ArrayType { Size = ((ArrayType)(typeInArray)).Size, SizeType = ArrayType.ArraySize.Constant, Type = innerArray }; unwrapCount = arrayType.Size / ((ArrayType)(typeInArray)).Size; // TODO: get type width from driver TargetInfo! unwrapTypeWidth = 0; } else if (!typeInArray.IsPrimitiveType()) { // need tp unwrap if field is array of complex type // Struct A[N] // becomes // Struct A_0; // Struct A_N; unwrapType = typeInArray; unwrapCount = arrayType.Size; // TODO: get type width from driver TargetInfo! unwrapTypeWidth = 0; } else { return(null); } return(new UnwrapInfo { UnwrapType = unwrapType, UnwrapCount = unwrapCount, UnwrapTypeWidth = unwrapTypeWidth }); }