private void DistributeMethod(Method method)
            {
                Type returnType = method.OriginalReturnType.Type.Desugar();

                if ((returnType.IsPrimitiveType(PrimitiveType.Void) ||
                     returnType.IsPrimitiveType(PrimitiveType.Bool)) &&
                    method.Parameters.Any(p => p.Kind == ParameterKind.Regular))
                {
                    if (method.Parameters.Count == 1)
                    {
                        setters.Add(method);
                    }
                    else if (method.Parameters.Count > 1)
                    {
                        setMethods.Add(method);
                    }
                }
                else
                {
                    if (method.ConvertToProperty || IsGetter(method))
                    {
                        getters.Add(method);
                    }
                    if (method.Parameters.All(p => p.Kind == ParameterKind.IndirectReturnType))
                    {
                        nonSetters.Add(method);
                    }
                }
            }
예제 #2
0
        public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
        {
            if (!VisitType(pointer, quals))
            {
                return(false);
            }

            var pointee = pointer.Pointee;

            Type type = pointee.Desugar();

            if ((type.IsPrimitiveType(PrimitiveType.Char) ||
                 type.IsPrimitiveType(PrimitiveType.WideChar)) &&
                pointer.QualifiedPointee.Qualifiers.IsConst)
            {
                Context.Return.Write("Marshal.StringToHGlobalAnsi({0})",
                                     Helpers.SafeIdentifier(Context.Parameter.Name));
                CSharpContext.Cleanup.WriteLine("Marshal.FreeHGlobal({0});",
                                                Helpers.SafeIdentifier(Context.ArgName));
                return(true);
            }

            if (pointee is FunctionType)
            {
                var function = pointee as FunctionType;
                return(VisitDelegateType(function, function.ToString()));
            }

            Class @class;

            if (type.IsTagDecl(out @class) && @class.IsValueType)
            {
                if (Context.Parameter.Usage == ParameterUsage.Out)
                {
                    Context.SupportBefore.WriteLine("var {0} = new {1}.Internal();",
                                                    Generator.GeneratedIdentifier(Context.ArgName), @class.Name);
                }
                else
                {
                    Context.SupportBefore.WriteLine("var {0} = {1}.ToInternal();",
                                                    Generator.GeneratedIdentifier(Context.ArgName),
                                                    Helpers.SafeIdentifier(Context.Parameter.Name));
                }

                Context.Return.Write("new global::System.IntPtr(&{0})",
                                     Generator.GeneratedIdentifier(Context.ArgName));
                return(true);
            }

            PrimitiveType primitive;

            if (type.IsPrimitiveType(out primitive))
            {
                Context.Return.Write(Context.Parameter.Name);
                return(true);
            }

            return(pointee.Visit(this, quals));
        }
        private static bool IsSetter(Method method)
        {
            Type returnType = method.OriginalReturnType.Type.Desugar();

            return((returnType.IsPrimitiveType(PrimitiveType.Void) ||
                    returnType.IsPrimitiveType(PrimitiveType.Bool)) &&
                   method.Parameters.Count(p => p.Kind == ParameterKind.Regular) == 1);
        }
예제 #4
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);
            const string intPtrType            = CSharpTypePrinter.IntPtrType;

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

            Context.Before.WriteLine($"if (ReferenceEquals({Context.Parameter.Name}, null))");
            Context.Before.WriteLineIndent($"{intermediateArray} = new[] {{ {intPtrType}.Zero }};");
            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];");
            Context.Before.WriteLine($@"{intermediateArray}[i] = ReferenceEquals({
                element}, null) ? {intPtrType}.Zero : {element}.{Helpers.InstanceIdentifier};");
            Context.Before.WriteCloseBraceIndent();

            Context.Before.WriteCloseBraceIndent();

            Context.Return.Write(intermediateArray);
        }
        private static bool CheckForEnumValue(Parameter parameter, Type desugared)
        {
            var enumItem = parameter.DefaultArgument.Declaration as Enumeration.Item;
            if (enumItem != null)
            {
                parameter.DefaultArgument.String = string.Format("{0}{1}{2}.{3}",
                    desugared.IsPrimitiveType() ? "(int) " : string.Empty,
                    string.IsNullOrEmpty(enumItem.Namespace.Namespace.Name)
                        ? string.Empty
                        : enumItem.Namespace.Namespace.Name + ".", enumItem.Namespace.Name, enumItem.Name);
                return true;
            }

            var call = parameter.DefaultArgument.Declaration as Function;
            if (call != null || parameter.DefaultArgument.Class == StatementClass.BinaryOperator)
            {
                string @params = regexFunctionParams.Match(parameter.DefaultArgument.String).Groups[1].Value;
                if (@params.Contains("::"))
                    parameter.DefaultArgument.String = regexDoubleColon.Replace(@params, desugared + ".");
                else
                    parameter.DefaultArgument.String = regexName.Replace(@params, desugared + ".$1");
                return true;
            }
            return false;
        }
        private static bool CheckForEnumValue(Parameter parameter, Type desugared)
        {
            var enumItem = parameter.DefaultArgument.Declaration as Enumeration.Item;

            if (enumItem != null)
            {
                parameter.DefaultArgument.String = string.Format("{0}{1}.{2}.{3}",
                                                                 desugared.IsPrimitiveType() ? "(int) " : string.Empty,
                                                                 enumItem.Namespace.Namespace.Name, enumItem.Namespace.Name, enumItem.Name);
                return(true);
            }

            var call = parameter.DefaultArgument.Declaration as Method;

            if (call != null && call.IsConstructor)
            {
                string @params =
                    regexFunctionParams.Match(parameter.DefaultArgument.String).Groups[1].Value;
                if (@params.Contains("::"))
                {
                    parameter.DefaultArgument.String = regexDoubleColon.Replace(@params, desugared + ".");
                }
                else
                {
                    parameter.DefaultArgument.String = regexName.Replace(@params, desugared + ".$1");
                }
                return(true);
            }
            return(false);
        }
 private void CheckForDefaultEmptyChar(Parameter parameter, Type desugared)
 {
     if (parameter.DefaultArgument.String == "0" && Driver.Options.MarshalCharAsManagedChar &&
         desugared.IsPrimitiveType(PrimitiveType.Char))
     {
         parameter.DefaultArgument.String = "'\\0'";
     }
 }
 private static bool IsSupportedArray(Type typeInArray)
 {
     if (typeInArray.IsPrimitiveType())
     {
         // no need to unwrap, as it is legal to have fixed arrays of primitive types (in C# pinvoke)
         return(true);
     }
     return(false);
 }
        private static void CheckForULongValue(Parameter parameter, Type desugared)
        {
            ulong  value;
            string @default = parameter.DefaultArgument.String;

            // HACK: .NET's Parse/TryParse have a bug preventing them from parsing UL-suffixed ulongs
            if (desugared.IsPrimitiveType() && @default.EndsWith("UL"))
            {
                @default = @default.Substring(0, @default.Length - 2);
            }
            if (ulong.TryParse(@default, out value))
            {
                parameter.DefaultArgument.String = value.ToString(CultureInfo.InvariantCulture);
            }
        }
예제 #10
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);
        }
        private static bool CheckForEnumValue(Expression arg, Type desugared)
        {
            var enumItem = arg.Declaration as Enumeration.Item;
            if (enumItem != null)
            {
                arg.String = string.Format("{0}{1}{2}.{3}",
                    desugared.IsPrimitiveType() ? "(int) " : string.Empty,
                    string.IsNullOrEmpty(enumItem.Namespace.Namespace.Name)
                        ? string.Empty
                        : enumItem.Namespace.Namespace.Name + ".", enumItem.Namespace.Name, enumItem.Name);
                return true;
            }

            var call = arg.Declaration as Function;
            if ((call != null || arg.Class == StatementClass.BinaryOperator) && arg.String != "0")
            {
                string @params = regexFunctionParams.Match(arg.String).Groups[1].Value;
                TranslateEnumExpression(arg, desugared, @params);
                return true;
            }
            return false;
        }
        private static bool CheckForEnumValue(Expression arg, Type desugared)
        {
            var enumItem = arg.Declaration as Enumeration.Item;

            if (enumItem != null)
            {
                arg.String = string.Format("{0}{1}{2}.{3}",
                                           desugared.IsPrimitiveType() ? "(int) " : string.Empty,
                                           string.IsNullOrEmpty(enumItem.Namespace.Namespace.Name)
                        ? string.Empty
                        : enumItem.Namespace.Namespace.Name + ".", enumItem.Namespace.Name, enumItem.Name);
                return(true);
            }

            var call = arg.Declaration as Function;

            if ((call != null || arg.Class == StatementClass.BinaryOperator) && arg.String != "0")
            {
                string @params = regexFunctionParams.Match(arg.String).Groups[1].Value;
                TranslateEnumExpression(arg, desugared, @params);
                return(true);
            }
            return(false);
        }
예제 #13
0
        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}");
        }
예제 #14
0
        public bool FindTypeMap(Type type, out TypeMap typeMap)
        {
            if (typeMaps.ContainsKey(type))
            {
                typeMap = typeMaps[type];
                return(typeMap.IsEnabled);
            }

            var template = type as TemplateSpecializationType;

            if (template != null)
            {
                var specialization = template.GetClassTemplateSpecialization();
                if (specialization != null &&
                    FindTypeMap(specialization, out typeMap))
                {
                    return(true);
                }
                if (template.Template.TemplatedDecl != null)
                {
                    if (FindTypeMap(template.Template.TemplatedDecl,
                                    out typeMap))
                    {
                        typeMap.Type = type;
                        return(true);
                    }
                    return(false);
                }
            }

            Type desugared = type.Desugar();

            desugared = (desugared.GetFinalPointee() ?? desugared).Desugar();
            bool printExtra = desugared.IsPrimitiveType() ||
                              (desugared.GetFinalPointee() ?? desugared).Desugar().IsPrimitiveType();
            var typePrinter = new CppTypePrinter
            {
                PrintTypeQualifiers = printExtra,
                PrintTypeModifiers  = printExtra,
                PrintLogicalNames   = true
            };

            foreach (var resolveTypeDefs in new[] { true, false })
            {
                foreach (var typePrintScopeKind in
                         new[] { TypePrintScopeKind.Local, TypePrintScopeKind.Qualified })
                {
                    typePrinter.ResolveTypedefs = resolveTypeDefs;
                    typePrinter.ScopeKind       = typePrintScopeKind;
                    if (FindTypeMap(type.Visit(typePrinter), out typeMap))
                    {
                        typeMap.Type   = type;
                        typeMaps[type] = typeMap;
                        return(true);
                    }
                }
            }

            typeMap = null;
            var typedef = type as TypedefType;

            return(typedef != null && FindTypeMap(typedef.Declaration.Type, out typeMap));
        }
        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
            });
        }
 private static void CheckForULongValue(Parameter parameter, Type desugared)
 {
     ulong value;
     string @default = parameter.DefaultArgument.String;
     // HACK: .NET's Parse/TryParse have a bug preventing them from parsing UL-suffixed ulongs
     if (desugared.IsPrimitiveType() && @default.EndsWith("UL"))
         @default = @default.Substring(0, @default.Length - 2);
     if (ulong.TryParse(@default, out value))
         parameter.DefaultArgument.String = value.ToString(CultureInfo.InvariantCulture);
 }
예제 #17
0
        public bool FindTypeMap(Type type, out TypeMap typeMap)
        {
            // Looks up the type in the cache map.
            if (typeMaps.ContainsKey(type))
            {
                typeMap      = typeMaps[type];
                typeMap.Type = type;
                return(typeMap.IsEnabled);
            }

            var template = type as TemplateSpecializationType;

            if (template != null)
            {
                var specialization = template.GetClassTemplateSpecialization();
                if (specialization != null &&
                    FindTypeMap(specialization, out typeMap))
                {
                    return(true);
                }

                if (template.Template.TemplatedDecl != null)
                {
                    if (FindTypeMap(template.Template.TemplatedDecl,
                                    out typeMap))
                    {
                        typeMap.Type = type;
                        return(true);
                    }

                    return(false);
                }
            }

            Type desugared = type.Desugar();

            desugared = (desugared.GetFinalPointee() ?? desugared).Desugar();

            bool printExtra = desugared.IsPrimitiveType() ||
                              (desugared.GetFinalPointee() ?? desugared).Desugar().IsPrimitiveType();

            var typePrinter = new CppTypePrinter(Context)
            {
                ResolveTypeMaps     = false,
                PrintTypeQualifiers = printExtra,
                PrintTypeModifiers  = printExtra,
                PrintLogicalNames   = true
            };

            typePrinter.PushContext(TypePrinterContextKind.Native);

            foreach (var resolveTypeDefs in new[] { false, true })
            {
                foreach (var typePrintScopeKind in
                         new[] { TypePrintScopeKind.Local, TypePrintScopeKind.Qualified })
                {
                    typePrinter.ResolveTypedefs = resolveTypeDefs;
                    typePrinter.PushScope(typePrintScopeKind);
                    var typeName = type.Visit(typePrinter);
                    typePrinter.PopScope();
                    if (FindTypeMap(typeName, out typeMap))
                    {
                        typeMap.Type   = type;
                        typeMaps[type] = typeMap;
                        return(true);
                    }
                }
            }

            typeMap = null;
            return(false);
        }
예제 #18
0
        public void GenerateFunctionCall(Function function, Class @class = null, Type publicRetType = null)
        {
            CheckArgumentRange(function);

            if (function.OperatorKind == CXXOperatorKind.EqualEqual ||
                function.OperatorKind == CXXOperatorKind.ExclaimEqual)
            {
                WriteLine("bool {0}Null = ReferenceEquals({0}, nullptr);",
                          function.Parameters[0].Name);
                WriteLine("bool {0}Null = ReferenceEquals({0}, nullptr);",
                          function.Parameters[1].Name);
                WriteLine("if ({0}Null || {1}Null)",
                          function.Parameters[0].Name, function.Parameters[1].Name);
                WriteLineIndent("return {0}{1}Null && {2}Null{3};",
                                function.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : "!(",
                                function.Parameters[0].Name, function.Parameters[1].Name,
                                function.OperatorKind == CXXOperatorKind.EqualEqual ? string.Empty : ")");
            }

            var retType = function.ReturnType;

            if (publicRetType == null)
            {
                publicRetType = retType.Type;
            }
            var needsReturn = !publicRetType.IsPrimitiveType(PrimitiveType.Void);

            const string valueMarshalName = "_this0";
            var          isValueType      = @class != null && @class.IsValueType;

            if (isValueType && !IsNativeFunctionOrStaticMethod(function))
            {
                WriteLine($"auto {valueMarshalName} = {typePrinter.PrintTag(@class)}::{@class.QualifiedOriginalName}();");

                var param = new Parameter {
                    Name = "(*this)", Namespace = function.Namespace
                };
                var ctx = new MarshalContext(Context, CurrentIndentation)
                {
                    Parameter = param
                };
                ctx.VarPrefix.Write(valueMarshalName);

                var marshal = new CLIMarshalManagedToNativePrinter(ctx);
                marshal.MarshalValueClassProperties(@class, valueMarshalName);

                if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
                {
                    Write(marshal.Context.Before);
                }
            }

            var @params = GenerateFunctionParamsMarshal(function.Parameters, function);

            var returnIdentifier = Helpers.ReturnIdentifier;

            if (needsReturn)
            {
                if (retType.Type.IsReference())
                {
                    Write("auto &{0} = ", returnIdentifier);
                }
                else
                {
                    Write("auto {0} = ", returnIdentifier);
                }
            }

            if (function.OperatorKind == CXXOperatorKind.Conversion ||
                function.OperatorKind == CXXOperatorKind.ExplicitConversion)
            {
                var method   = function as Method;
                var typeName = method.ConversionType.Visit(new CppTypePrinter(Context));
                WriteLine("({0}) {1};", typeName, @params[0].Name);
            }
            else if (function.IsOperator &&
                     function.OperatorKind != CXXOperatorKind.Subscript)
            {
                var opName = function.Name.Replace("operator", "").Trim();

                switch (Operators.ClassifyOperator(function))
                {
                case CXXOperatorArity.Unary:
                    WriteLine("{0} {1};", opName, @params[0].Name);
                    break;

                case CXXOperatorArity.Binary:
                    WriteLine("{0} {1} {2};", @params[0].Name, opName, @params[1].Name);
                    break;
                }
            }
            else
            {
                if (IsNativeFunctionOrStaticMethod(function))
                {
                    Write($"::{function.QualifiedOriginalName}(");
                }
                else
                {
                    if (isValueType)
                    {
                        Write($"{valueMarshalName}.");
                    }
                    else if (IsNativeMethod(function))
                    {
                        Write($"(({typePrinter.PrintTag(@class)}::{@class.QualifiedOriginalName}*)NativePtr)->");
                    }
                    Write("{0}(", function.OriginalName);
                }

                GenerateFunctionParams(@params);
                WriteLine(");");
            }

            foreach (var paramInfo in @params)
            {
                var param = paramInfo.Param;
                if (param.Usage != ParameterUsage.Out && param.Usage != ParameterUsage.InOut)
                {
                    continue;
                }

                if (param.Type.IsPointer() && !param.Type.GetFinalPointee().IsPrimitiveType())
                {
                    param.QualifiedType = new QualifiedType(param.Type.GetFinalPointee());
                }

                var nativeVarName = paramInfo.Name;

                var ctx = new MarshalContext(Context, CurrentIndentation)
                {
                    ArgName       = nativeVarName,
                    ReturnVarName = nativeVarName,
                    ReturnType    = param.QualifiedType
                };

                var marshal = new CLIMarshalNativeToManagedPrinter(ctx);
                param.Visit(marshal);

                if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
                {
                    Write(marshal.Context.Before);
                }

                WriteLine("{0} = {1};", param.Name, marshal.Context.Return);
            }

            if (isValueType && !IsNativeFunctionOrStaticMethod(function))
            {
                GenerateStructMarshaling(@class, valueMarshalName + ".");
            }

            if (needsReturn)
            {
                var retTypeName = retType.Visit(CTypePrinter).ToString();
                var isIntPtr    = retTypeName.Contains("IntPtr");

                if (retType.Type.IsPointer() && (isIntPtr || retTypeName.EndsWith("^", StringComparison.Ordinal)))
                {
                    WriteLine("if ({0} == nullptr) return {1};",
                              returnIdentifier,
                              isIntPtr ? "::System::IntPtr()" : "nullptr");
                }

                var ctx = new MarshalContext(Context, CurrentIndentation)
                {
                    ArgName       = returnIdentifier,
                    ReturnVarName = returnIdentifier,
                    ReturnType    = retType
                };

                var marshal = new CLIMarshalNativeToManagedPrinter(ctx);
                retType.Visit(marshal);

                if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
                {
                    Write(marshal.Context.Before);
                }

                // Special case for indexer - needs to dereference if the internal
                // function is a pointer type and the property is not.
                if (retType.Type.IsPointer() &&
                    retType.Type.GetPointee().Equals(publicRetType) &&
                    publicRetType.IsPrimitiveType())
                {
                    WriteLine("return *({0});", marshal.Context.Return);
                }
                else if (retType.Type.IsReference() && publicRetType.IsReference())
                {
                    WriteLine("return ({0})({1});", publicRetType, marshal.Context.Return);
                }
                else
                {
                    WriteLine("return {0};", marshal.Context.Return);
                }
            }
        }
예제 #19
0
        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)) ||
                    (arrayType.IsPrimitiveType() && MarshalKind != CSharpMarshalKind.NativeField))
                {
                    if (primitiveType == PrimitiveType.Void)
                    {
                        return("void*");
                    }
                    return(string.Format("{0}", array.Type.Visit(this, quals)));
                }

                if (TypePrinterContext.Parameter != null)
                {
                    return(string.Format("global::System.IntPtr"));
                }

                Enumeration @enum;
                if (arrayType.TryGetEnum(out @enum))
                {
                    return(new CSharpTypePrinterResult
                    {
                        Type = string.Format("fixed {0}", @enum.BuiltinType),
                        NameSuffix = string.Format("[{0}]", array.Size)
                    });
                }

                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 = 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 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}{1}", array.Type.Visit(this),
                                 array.SizeType == ArrayType.ArraySize.Constant ? "[]" :
                                 (ContextKind == CSharpTypePrinterContextKind.Managed ? "*" : string.Empty)));

            // C# only supports fixed arrays in unsafe sections
            // and they are constrained to a set of built-in types.
        }
 private void CheckForDefaultEmptyChar(Parameter parameter, Type desugared)
 {
     if (parameter.DefaultArgument.String == "0" && Driver.Options.MarshalCharAsManagedChar &&
         desugared.IsPrimitiveType(PrimitiveType.Char))
     {
         parameter.DefaultArgument.String = "'\\0'";
     }
 }