Beispiel #1
0
        private void GenerateValueTypeConstructorCall(Method method, Class @class)
        {
            var names = new List <string>();

            foreach (var param in method.Parameters)
            {
                var ctx = new MarshalContext(Driver)
                {
                    Parameter = param,
                    ArgName   = param.Name,
                };

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

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

                names.Add(marshal.Context.Return);
            }

            WriteLine("::{0} _native({1});", @class.QualifiedOriginalName,
                      string.Join(", ", names));

            GenerateValueTypeConstructorCallFields(@class);
        }
Beispiel #2
0
        private void GenerateValueTypeConstructorCall(Method method, Class @class)
        {
            var names = new List <string>();

            var paramIndex = 0;

            foreach (var param in method.Parameters)
            {
                var ctx = new MarshalContext(Context, CurrentIndentation)
                {
                    Function       = method,
                    Parameter      = param,
                    ArgName        = param.Name,
                    ParameterIndex = paramIndex++
                };

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

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

                names.Add(marshal.Context.Return);
            }

            WriteLine($@"{typePrinter.PrintTag(@class)}::{
                @class.QualifiedOriginalName} _native({string.Join(", ", names)});");

            GenerateValueTypeConstructorCallProperties(@class);
        }
Beispiel #3
0
        private ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex,
                                                          Function function = null)
        {
            if (param.Type is BuiltinType)
            {
                return(new ParamMarshal {
                    Name = param.Name, Param = param
                });
            }

            var argName = "arg" + paramIndex.ToString(CultureInfo.InvariantCulture);

            if (param.Usage == ParameterUsage.Out)
            {
                var paramType = param.Type;
                if (paramType.IsReference())
                {
                    paramType = (paramType as PointerType).Pointee;
                }

                var typePrinter = new CppTypePrinter(Driver.TypeDatabase);
                var type        = paramType.Visit(typePrinter);

                WriteLine("{0} {1};", type, argName);
            }
            else
            {
                var ctx = new MarshalContext(Driver)
                {
                    Parameter      = param,
                    ParameterIndex = paramIndex,
                    ArgName        = argName,
                    Function       = function
                };

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

                if (string.IsNullOrEmpty(marshal.Context.Return))
                {
                    throw new Exception("Cannot marshal argument of function");
                }

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

                WriteLine("auto {0}{1} = {2};", marshal.VarPrefix, argName,
                          marshal.Context.Return);
                argName = marshal.ArgumentPrefix + argName;
            }

            return(new ParamMarshal {
                Name = argName, Param = param
            });
        }
Beispiel #4
0
        private void MarshalValueClassProperty(Property property, string marshalVar)
        {
            var fieldRef = string.Format("{0}.{1}", Context.Parameter.Name,
                                         property.Name);

            var marshalCtx = new MarshalContext(Context.Context, Context.Indentation)
            {
                ArgName          = fieldRef,
                ParameterIndex   = Context.ParameterIndex++,
                MarshalVarPrefix = Context.MarshalVarPrefix,
                ReturnVarName    = $"{marshalVar}.{property.Field.OriginalName}"
            };

            var marshal = new CLIMarshalManagedToNativePrinter(marshalCtx);

            property.Visit(marshal);

            Context.ParameterIndex = marshalCtx.ParameterIndex;

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

            if (!string.IsNullOrWhiteSpace(marshal.Context.Return))
            {
                Type  type;
                Class @class;
                var   isRef = property.Type.IsPointerTo(out type) &&
                              !(type.TryGetClass(out @class) && @class.IsValueType) &&
                              !type.IsPrimitiveType();

                if (isRef)
                {
                    Context.Before.WriteLine("if ({0} != nullptr)", fieldRef);
                    Context.Before.Indent();
                }

                Context.Before.WriteLine("{0}.{1} = {2};", marshalVar,
                                         property.Field.OriginalName, marshal.Context.Return);

                if (isRef)
                {
                    Context.Before.Unindent();
                }
            }
        }
Beispiel #5
0
        private void MarshalValueClassField(Field field, string marshalVar)
        {
            var fieldRef = string.Format("{0}.{1}", Context.Parameter.Name,
                                         field.Name);

            var marshalCtx = new MarshalContext(Context.Driver)
            {
                ArgName        = fieldRef,
                ParameterIndex = Context.ParameterIndex++
            };

            var marshal = new CLIMarshalManagedToNativePrinter(marshalCtx);

            field.Visit(marshal);

            Context.ParameterIndex = marshalCtx.ParameterIndex;

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

            if (field.Type.IsPointer())
            {
                Context.SupportBefore.WriteLine("if ({0} != nullptr)", fieldRef);
                Context.SupportBefore.PushIndent();
            }

            Context.SupportBefore.WriteLine("{0}.{1} = {2};", marshalVar, field.OriginalName,
                                            marshal.Context.Return);

            if (field.Type.IsPointer())
            {
                Context.SupportBefore.PopIndent();
            }
        }
Beispiel #6
0
        private ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex,
                                                          Function function = null)
        {
            var paramMarshal = new ParamMarshal {
                Name = param.Name, Param = param
            };

            if (param.Type is BuiltinType)
            {
                return(paramMarshal);
            }

            var argName = Generator.GeneratedIdentifier("arg") + paramIndex.ToString(CultureInfo.InvariantCulture);

            var isRef = param.IsOut || param.IsInOut;

            var paramType = param.Type;

            // Get actual type if the param type is a typedef but not a function type because function types have to be typedef.
            // We need to get the actual type this early before we visit any marshalling code to ensure we hit the marshalling
            // logic for the actual type and not the typedef.
            // This fixes issues where typedefs to primitive pointers are involved.
            FunctionType functionType;
            var          paramTypeAsTypedef = paramType as TypedefType;

            if (paramTypeAsTypedef != null && !paramTypeAsTypedef.Declaration.Type.IsPointerTo(out functionType))
            {
                paramType = param.Type.Desugar();
            }

            // Since both pointers and references to types are wrapped as CLI
            // tracking references when using in/out, we normalize them here to be able
            // to use the same code for marshaling.
            if (paramType is PointerType && isRef)
            {
                if (!paramType.IsReference())
                {
                    paramMarshal.Prefix = "&";
                }
                paramType = (paramType as PointerType).Pointee;
            }

            var effectiveParam = new Parameter(param)
            {
                QualifiedType = new QualifiedType(paramType)
            };

            var ctx = new MarshalContext(Context, CurrentIndentation)
            {
                Parameter      = effectiveParam,
                ParameterIndex = paramIndex,
                ArgName        = argName,
                Function       = function
            };

            var marshal = new CLIMarshalManagedToNativePrinter(ctx);

            effectiveParam.Visit(marshal);

            if (string.IsNullOrEmpty(marshal.Context.Return))
            {
                throw new Exception($"Cannot marshal argument of function '{function.QualifiedOriginalName}'");
            }

            if (isRef)
            {
                var typePrinter = new CppTypePrinter(Context)
                {
                    ResolveTypeMaps = false
                };
                var type = paramType.Visit(typePrinter);

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

                    WriteLine("{0} {1} = {2};", type, argName, marshal.Context.Return);
                }
                else
                {
                    WriteLine("{0} {1};", type, argName);
                }
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
                {
                    Write(marshal.Context.Before);
                }

                WriteLine("auto {0}{1} = {2};", marshal.VarPrefix, argName,
                          marshal.Context.Return);
                paramMarshal.Prefix = marshal.ArgumentPrefix;
            }

            paramMarshal.Name = argName;
            return(paramMarshal);
        }
Beispiel #7
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);
                }
            }
        }
Beispiel #8
0
        private ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex,
                                                          Function function = null)
        {
            var paramMarshal = new ParamMarshal {
                Name = param.Name, Param = param
            };

            if (param.Type is BuiltinType)
            {
                return(paramMarshal);
            }

            var argName = Generator.GeneratedIdentifier("arg") + paramIndex.ToString(CultureInfo.InvariantCulture);

            var isRef = param.IsOut || param.IsInOut;
            // Since both pointers and references to types are wrapped as CLI
            // tracking references when using in/out, we normalize them here to be able
            // to use the same code for marshaling.
            var paramType = param.Type;

            if (paramType is PointerType && isRef)
            {
                if (!paramType.IsReference())
                {
                    paramMarshal.Prefix = "&";
                }
                paramType = (paramType as PointerType).Pointee;
            }

            var effectiveParam = new Parameter(param)
            {
                QualifiedType = new QualifiedType(paramType)
            };

            var ctx = new MarshalContext(Context)
            {
                Parameter      = effectiveParam,
                ParameterIndex = paramIndex,
                ArgName        = argName,
                Function       = function
            };

            var marshal = new CLIMarshalManagedToNativePrinter(ctx);

            effectiveParam.Visit(marshal);

            if (string.IsNullOrEmpty(marshal.Context.Return))
            {
                throw new Exception(string.Format("Cannot marshal argument of function '{0}'",
                                                  function.QualifiedOriginalName));
            }

            if (isRef)
            {
                var typePrinter = new CppTypePrinter();
                var type        = paramType.Visit(typePrinter);

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

                    WriteLine("{0} {1} = {2};", type, argName, marshal.Context.Return);
                }
                else
                {
                    WriteLine("{0} {1};", type, argName);
                }
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
                {
                    Write(marshal.Context.Before);
                }

                WriteLine("auto {0}{1} = {2};", marshal.VarPrefix, argName,
                          marshal.Context.Return);
                paramMarshal.Prefix = marshal.ArgumentPrefix;
            }

            paramMarshal.Name = argName;
            return(paramMarshal);
        }
Beispiel #9
0
        public override void CLIMarshalToNative(MarshalContext ctx)
        {
            var templateType = Type as TemplateSpecializationType;
            var type = templateType.Arguments[0].Type;
            var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType();
            var managedType = isPointerToPrimitive
                ? new CILType(typeof(System.IntPtr))
                : type.Type;

            var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name
                : ctx.ArgName;

            var tmpVarName = "_tmp" + entryString;

            var cppTypePrinter = new CppTypePrinter();
            var nativeType = type.Type.Visit(cppTypePrinter);

            ctx.SupportBefore.WriteLine("auto {0} = std::vector<{1}>();",
                tmpVarName, nativeType);
            ctx.SupportBefore.WriteLine("for each({0} _element in {1})",
                managedType, entryString);
            ctx.SupportBefore.WriteStartBraceIndent();
            {
                var param = new Parameter
                {
                    Name = "_element",
                    QualifiedType = type
                };

                var elementCtx = new MarshalContext(ctx.Context)
                                     {
                                         Parameter = param,
                                         ArgName = param.Name,
                                     };

                var marshal = new CLIMarshalManagedToNativePrinter(elementCtx);
                type.Type.Visit(marshal);

                if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
                    ctx.SupportBefore.Write(marshal.Context.SupportBefore);

                if (isPointerToPrimitive)
                    ctx.SupportBefore.WriteLine("auto _marshalElement = {0}.ToPointer();",
                        marshal.Context.Return);
                else
                    ctx.SupportBefore.WriteLine("auto _marshalElement = {0};",
                    marshal.Context.Return);

                ctx.SupportBefore.WriteLine("{0}.push_back(_marshalElement);",
                    tmpVarName);
            }
            
            ctx.SupportBefore.WriteCloseBraceIndent();

            ctx.Return.Write(tmpVarName);
        }
Beispiel #10
0
        public void GenerateFunctionCall(Function function, Class @class = null)
        {
            var retType     = function.ReturnType;
            var needsReturn = !retType.Type.IsPrimitiveType(PrimitiveType.Void);

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

            if (isValueType && !IsNativeFunctionOrStaticMethod(function))
            {
                WriteLine("auto {0} = ::{1}();", valueMarshalName, @class.QualifiedOriginalName);

                var param = new Parameter {
                    Name = "(*this)"
                };
                var ctx = new MarshalContext(Driver)
                {
                    MarshalVarPrefix = valueMarshalName,
                    Parameter        = param
                };

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

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

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

            if (needsReturn)
            {
                Write("auto {0}{1} = ", (function.ReturnType.Type.IsReference())? "&": string.Empty,
                      Generator.GeneratedIdentifier("ret"));
            }

            if (function.OperatorKind == CXXOperatorKind.Conversion)
            {
                var method      = function as Method;
                var typePrinter = new CppTypePrinter(Driver.TypeDatabase);
                var typeName    = method.ConversionType.Visit(typePrinter);
                WriteLine("({0}) {1};", typeName, @params[0].Name);
            }
            else if (function.IsOperator)
            {
                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("::{0}(", function.QualifiedOriginalName);
                }
                else
                {
                    if (isValueType)
                    {
                        Write("{0}.", valueMarshalName);
                    }
                    else if (IsNativeMethod(function))
                    {
                        Write("((::{0}*)NativePtr)->", @class.QualifiedOriginalName);
                    }
                    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;
                }

                var nativeVarName = paramInfo.Name;

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

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

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

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

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

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

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

                var ctx = new MarshalContext(Driver)
                {
                    ArgName       = Generator.GeneratedIdentifier("ret"),
                    ReturnVarName = Generator.GeneratedIdentifier("ret"),
                    ReturnType    = retType
                };

                var marshal = new CLIMarshalNativeToManagedPrinter(ctx);
                function.ReturnType.Visit(marshal);

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

                WriteLine("return {0};", marshal.Context.Return);
            }
        }
Beispiel #11
0
        public override void CLIMarshalToNative(MarshalContext ctx)
        {
            var templateType = Type as TemplateSpecializationType;
            var type = templateType.Arguments[0].Type;

            var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name : ctx.ArgName;

            var tmpVarName = "_tmp" + entryString;

            var cppTypePrinter = new CppTypePrinter(ctx.Driver.TypeDatabase);
            var nativeType = type.Type.Visit(cppTypePrinter);

            ctx.SupportBefore.WriteLine("auto {0} = Vector<{1}>();",
                tmpVarName, nativeType);
            ctx.SupportBefore.WriteLine("for each({0} _element in {1})",
                type.ToString(), entryString);
            ctx.SupportBefore.WriteStartBraceIndent();
            {
                var param = new Parameter
                {
                    Name = "_element",
                    QualifiedType = type
                };

                var elementCtx = new MarshalContext(ctx.Driver)
                {
                    Parameter = param,
                    ArgName = param.Name,
                };

                var marshal = new CLIMarshalManagedToNativePrinter(elementCtx);
                type.Type.Visit(marshal);

                if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
                    ctx.SupportBefore.Write(marshal.Context.SupportBefore);

                ctx.SupportBefore.WriteLine("auto _marshalElement = {0};",
                    marshal.Context.Return);

                ctx.SupportBefore.WriteLine("{0}.Push(_marshalElement);", tmpVarName);
            }

            ctx.SupportBefore.WriteCloseBraceIndent();

            ctx.Return.Write(tmpVarName);
        }
Beispiel #12
0
        private void GeneratePropertySetter <T>(T decl, Class @class, string name, Type type, Parameter indexParameter = null)
            where T : Declaration, ITypedDecl
        {
            if (decl == null)
            {
                return;
            }

            var args      = new List <string>();
            var isIndexer = indexParameter != null;

            if (isIndexer)
            {
                args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name));
            }

            var function = decl as Function;
            var argName  = function != null && !isIndexer ? function.Parameters[0].Name : "value";

            args.Add(string.Format("{0} {1}", type, argName));

            WriteLine("void {0}::{1}::set({2})", QualifiedIdentifier(@class),
                      name, string.Join(", ", args));

            WriteStartBraceIndent();

            if (decl is Function && !isIndexer)
            {
                var func = decl as Function;
                GenerateFunctionCall(func, @class);
            }
            else
            {
                if (@class.IsValueType && decl is Field)
                {
                    WriteLine("{0} = value;", decl.Name);
                    WriteCloseBraceIndent();
                    NewLine();
                    return;
                }
                var param = new Parameter
                {
                    Name          = "value",
                    QualifiedType = new QualifiedType(type)
                };

                var ctx = new MarshalContext(Driver)
                {
                    Parameter = param,
                    ArgName   = param.Name,
                };

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

                string variable;
                if (decl is Variable)
                {
                    variable = string.Format("::{0}::{1}",
                                             @class.QualifiedOriginalName, decl.OriginalName);
                }
                else
                {
                    variable = string.Format("((::{0}*)NativePtr)->{1}",
                                             @class.QualifiedOriginalName, decl.OriginalName);
                }

                if (isIndexer)
                {
                    variable += string.Format("({0})", indexParameter.Name);
                }

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

                if (isIndexer && decl.Type.IsPointer())
                {
                    WriteLine("*({0}) = {1};", variable, marshal.Context.Return);
                }
                else
                {
                    WriteLine("{0} = {1};", variable, marshal.Context.Return);
                }
            }

            WriteCloseBraceIndent();
            NewLine();
        }
Beispiel #13
0
        private void MarshalValueClassProperty(Property property, string marshalVar)
        {
            var fieldRef = string.Format("{0}.{1}", Context.Parameter.Name,
                                         property.Name);

            var marshalCtx = new MarshalContext(Context.Driver)
                                 {
                                     ArgName = fieldRef,
                                     ParameterIndex = Context.ParameterIndex++,
                                     MarshalVarPrefix = Context.MarshalVarPrefix
                                 };

            var marshal = new CLIMarshalManagedToNativePrinter(marshalCtx);
            property.Visit(marshal);

            Context.ParameterIndex = marshalCtx.ParameterIndex;

            if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
                Context.SupportBefore.Write(marshal.Context.SupportBefore);

            Type type;
            Class @class;
            var isRef = property.Type.IsPointerTo(out type) &&
                !(type.TryGetClass(out @class) && @class.IsValueType) &&
                !type.IsPrimitiveType();

            if (isRef)
            {
                Context.SupportBefore.WriteLine("if ({0} != nullptr)", fieldRef);
                Context.SupportBefore.PushIndent();
            }

            Context.SupportBefore.WriteLine("{0}.{1} = {2};", marshalVar,
                property.Field.OriginalName, marshal.Context.Return);

            if (isRef)
                Context.SupportBefore.PopIndent();
        }
Beispiel #14
0
        private void MarshalValueClassField(Field field, string marshalVar)
        {
            var fieldRef = string.Format("{0}.{1}", Context.Parameter.Name,
                                         field.Name);

            var marshalCtx = new MarshalContext(Context.Driver)
                                 {
                                     ArgName = fieldRef,
                                     ParameterIndex = Context.ParameterIndex++,
                                     MarshalVarPrefix = Context.MarshalVarPrefix
                                 };

            var marshal = new CLIMarshalManagedToNativePrinter(marshalCtx);
            field.Visit(marshal);

            Context.ParameterIndex = marshalCtx.ParameterIndex;

            if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
                Context.SupportBefore.Write(marshal.Context.SupportBefore);

            if(field.Type.IsPointer())
            {
                Context.SupportBefore.WriteLine("if ({0} != nullptr)", fieldRef);
                Context.SupportBefore.PushIndent();
            }

            Context.SupportBefore.WriteLine("{0}.{1} = {2};", marshalVar, field.OriginalName,
                                    marshal.Context.Return);

            if(field.Type.IsPointer())
                Context.SupportBefore.PopIndent();
        }
Beispiel #15
0
        private void GeneratePropertySetter <T>(T decl, Class @class, string name, Type type, Parameter indexParameter = null)
            where T : Declaration, ITypedDecl
        {
            if (decl == null)
            {
                return;
            }

            var args      = new List <string>();
            var isIndexer = indexParameter != null;

            if (isIndexer)
            {
                args.Add($"{indexParameter.Type} {indexParameter.Name}");
            }

            var function = decl as Function;
            var argName  = function != null && !isIndexer ? function.Parameters[0].Name : "value";

            args.Add($"{type} {argName}");

            WriteLine("void {0}::{1}::set({2})", QualifiedIdentifier(@class),
                      name, string.Join(", ", args));

            WriteOpenBraceAndIndent();

            if (decl is Function && !isIndexer)
            {
                var func  = decl as Function;
                var @void = new BuiltinType(PrimitiveType.Void);
                GenerateFunctionCall(func, @class, @void);
            }
            else
            {
                if (@class.IsValueType && decl is Field)
                {
                    WriteLine("{0} = value;", decl.Name);
                    UnindentAndWriteCloseBrace();
                    NewLine();
                    return;
                }
                var param = new Parameter
                {
                    Name          = "value",
                    QualifiedType = new QualifiedType(type)
                };

                string variable;
                if (decl is Variable)
                {
                    variable = $"::{@class.QualifiedOriginalName}::{decl.OriginalName}";
                }
                else
                {
                    variable = $"(({typePrinter.PrintTag(@class)}::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}";
                }

                var ctx = new MarshalContext(Context, CurrentIndentation)
                {
                    Parameter     = param,
                    ArgName       = param.Name,
                    ReturnVarName = variable
                };

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

                if (isIndexer)
                {
                    var ctx2 = new MarshalContext(Context, CurrentIndentation)
                    {
                        Parameter = indexParameter,
                        ArgName   = indexParameter.Name
                    };

                    var marshal2 = new CLIMarshalManagedToNativePrinter(ctx2);
                    indexParameter.Visit(marshal2);

                    variable += string.Format("({0})", marshal2.Context.Return);
                }

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

                if (marshal.Context.Return.StringBuilder.Length > 0)
                {
                    if (isIndexer && decl.Type.IsPointer())
                    {
                        WriteLine("*({0}) = {1};", variable, marshal.Context.Return);
                    }
                    else
                    {
                        WriteLine("{0} = {1};", variable, marshal.Context.Return);
                    }
                }
            }

            UnindentAndWriteCloseBrace();
            NewLine();
        }
Beispiel #16
0
        private void GeneratePropertySetter <T>(T decl, Class @class, string name, Type type)
            where T : Declaration, ITypedDecl
        {
            if (decl == null)
            {
                return;
            }

            WriteLine("void {0}::{1}::set({2} value)", QualifiedIdentifier(@class),
                      name, type);
            WriteStartBraceIndent();

            if (decl is Function)
            {
                var func = decl as Function;
                if (func.Parameters[0].Name != "value")
                {
                    WriteLine("auto {0} = value;", func.Parameters[0].Name);
                }
                GenerateFunctionCall(func, @class);
            }
            else
            {
                if (@class.IsValueType && decl is Field)
                {
                    WriteLine("{0} = value;", decl.Name);
                    WriteCloseBraceIndent();
                    NewLine();
                    return;
                }
                var param = new Parameter
                {
                    Name          = "value",
                    QualifiedType = decl.QualifiedType
                };

                var ctx = new MarshalContext(Driver)
                {
                    Parameter = param,
                    ArgName   = param.Name,
                };

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

                string variable;
                if (decl is Variable)
                {
                    variable = string.Format("::{0}::{1}",
                                             @class.QualifiedOriginalName, decl.OriginalName);
                }
                else
                {
                    variable = string.Format("((::{0}*)NativePtr)->{1}",
                                             @class.QualifiedOriginalName, decl.OriginalName);
                }

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

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

            WriteCloseBraceIndent();
            NewLine();
        }
Beispiel #17
0
        public override void CLIMarshalToNative(MarshalContext ctx)
        {
            var templateType = Type as TemplateSpecializationType;
            var type1 = templateType.Arguments[0].Type;
            var type2 = templateType.Arguments[1].Type;

            var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name : ctx.ArgName;

            var tmpVarName = "_tmp" + entryString;

            var cppTypePrinter = new CppTypePrinter(ctx.Driver.TypeDatabase);
            var nativeType1 = type1.Type.Visit(cppTypePrinter);
            var nativeType2 = type2.Type.Visit(cppTypePrinter);

            ctx.SupportBefore.WriteLine("auto {0} = HashMap<{1}, {2}>();",
                tmpVarName, nativeType1, nativeType2);
            ctx.SupportBefore.WriteLine("auto _keys = {0}->Keys->GetEnumerator();", entryString);
            ctx.SupportBefore.WriteLine("while (_keys.MoveNext())");
            ctx.SupportBefore.WriteStartBraceIndent();
            {
                ctx.SupportBefore.WriteLine("{0} _key = _keys.Current;", type1.ToString());
                ctx.SupportBefore.WriteLine("{0} _val = {1}[_key];", type2.ToString(), entryString);
                var param1 = new Parameter
                {
                    Name = "_key",
                    QualifiedType = type1
                };

                var elementCtx1 = new MarshalContext(ctx.Driver)
                {
                    Parameter = param1,
                    ArgName = param1.Name,
                };

                var marshal1 = new CLIMarshalManagedToNativePrinter(elementCtx1);
                type1.Type.Visit(marshal1);

                if (!string.IsNullOrWhiteSpace(marshal1.Context.SupportBefore))
                    ctx.SupportBefore.Write(marshal1.Context.SupportBefore);

                ctx.SupportBefore.WriteLine("auto _marshalKey = {0};",
                    marshal1.Context.Return);

                var param2 = new Parameter
                {
                    Name = "_val",
                    QualifiedType = type2
                };

                var elementCtx2 = new MarshalContext(ctx.Driver)
                {
                    Parameter = param2,
                    ArgName = param2.Name,
                };

                var marshal2 = new CLIMarshalManagedToNativePrinter(elementCtx2);
                type2.Type.Visit(marshal2);

                if (!string.IsNullOrWhiteSpace(marshal2.Context.SupportBefore))
                    ctx.SupportBefore.Write(marshal2.Context.SupportBefore);

                ctx.SupportBefore.WriteLine("auto _marshalValue = {0};",
                    marshal2.Context.Return);

                ctx.SupportBefore.WriteLine("{0}[_marshalKey] = _marshalValue;", tmpVarName);
            }

            ctx.SupportBefore.WriteCloseBraceIndent();

            ctx.Return.Write(tmpVarName);
        }