Beispiel #1
0
        public override bool VisitManagedArrayType(ManagedArrayType array,
                                                   TypeQualifiers quals)
        {
            var support = Context.SupportBefore;

            var contextId      = CGenerator.GenId("mono_context");
            var arrayId        = CGenerator.GenId(string.Format("{0}_array", Context.ArgName));
            var elementClassId = CGenerator.GenId(string.Format("{0}_element_class",
                                                                Context.ArgName));

            var managedArray = array.Array;
            var elementType  = managedArray.Type;

            support.WriteLine("MonoClass* {0} = mono_class_get_element_class({1});",
                              elementClassId, GenerateArrayTypeLookup(elementType, support));

            support.WriteLine("MonoArray* {0} = mono_array_new({1}.domain, {2}, {3}.array->len);",
                              arrayId, contextId, elementClassId, Context.ArgName);

            var iteratorId = CGenerator.GenId("i");

            support.WriteLine("for (int {0} = 0; {0} < {1}.array->len; {0}++)",
                              iteratorId, Context.ArgName);
            support.WriteStartBraceIndent();

            var    typePrinter     = CTypePrinter;
            string elementTypeName = elementType.Visit(typePrinter);

            var elementId = CGenerator.GenId(string.Format("{0}_array_element",
                                                           Context.ArgName));

            support.WriteLine("{0} {1} = g_array_index({2}.array, {0}, {3});",
                              elementTypeName, elementId, Context.ArgName, iteratorId);

            var ctx = new MarshalContext(Context.Context)
            {
                ArgName = elementId,
            };


            var marshal = new CMarshalNativeToManaged(ctx)
            {
                PrimitiveValuesByValue = true
            };

            elementType.Visit(marshal);

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

            var isValueType = IsValueType(elementType);

            if (isValueType)
            {
                support.WriteLine("mono_array_set({0}, {1}, {2}, {3});",
                                  arrayId, elementTypeName, iteratorId,
                                  marshal.Context.Return.ToString());
            }
            else
            {
                support.WriteLine("mono_array_setref({0}, {1}, {2});",
                                  arrayId, iteratorId, marshal.Context.Return.ToString());
            }

            support.WriteCloseBraceIndent();

            Context.Return.Write("{0}", arrayId);

            return(true);
        }
Beispiel #2
0
        public override bool VisitManagedArrayType(ManagedArrayType array,
                                                   TypeQualifiers quals)
        {
            var support = Context.SupportBefore;

            var arrayId = CGenerator.GenId(string.Format("{0}_array",
                                                         Context.ArgName));

            support.WriteLine("MonoArray* {0} = (MonoArray*) {1};",
                              arrayId, Context.ArgName);

            var arraySizeId = CGenerator.GenId(string.Format("{0}_array_size",
                                                             Context.ArgName));

            support.WriteLine("uintptr_t {0} = mono_array_length({1});",
                              arraySizeId, arrayId);

            var typePrinter = CTypePrinter;

            typePrinter.PrintScopeKind = CppTypePrintScopeKind.Local;
            var arrayTypedefName = array.Typedef.Visit(typePrinter);

            typePrinter.PrintScopeKind = CppTypePrintScopeKind.Qualified;
            var arrayElementName = array.Array.Type.Visit(typePrinter);
            var elementSize      = string.Format("sizeof({0})", arrayElementName);

            var nativeArrayId = CGenerator.GenId(string.Format("{0}_native_array",
                                                               Context.ArgName));

            support.WriteLine("{0} {1};", arrayTypedefName, nativeArrayId);
            support.WriteLine("{0}.array = g_array_sized_new(/*zero_terminated=*/FALSE," +
                              " /*clear_=*/TRUE, {1}, {2});", nativeArrayId, elementSize, arraySizeId);

            var elementClassId = CGenerator.GenId(string.Format("{0}_element_class",
                                                                Context.ArgName));

            support.WriteLine("MonoClass* {0} = mono_class_get_element_class({1});",
                              elementClassId,
                              CMarshalNativeToManaged.GenerateArrayTypeLookup(array.Array.Type, support));

            var elementSizeId = CGenerator.GenId(string.Format("{0}_array_element_size",
                                                               Context.ArgName));

            support.WriteLine("gint32 {0} = mono_class_array_element_size({1});",
                              elementSizeId, elementClassId);

            var iteratorId = CGenerator.GenId("i");

            support.WriteLine("for (int {0} = 0; {0} < {1}; {0}++)",
                              iteratorId, arraySizeId);
            support.WriteStartBraceIndent();

            var elementId = CGenerator.GenId(string.Format("{0}_array_element",
                                                           Context.ArgName));

            var isValueType = CMarshalNativeToManaged.IsValueType(array.Array.Type);

            support.WriteLine("{5} {0} = {4}mono_array_addr_with_size({1}, {2}, {3});",
                              elementId, arrayId, elementSizeId, iteratorId,
                              isValueType ? string.Empty : "*(MonoObject**)",
                              isValueType ? "char*" : "MonoObject*");

            var ctx = new MarshalContext(Context.Context)
            {
                ArgName       = elementId,
                ReturnVarName = elementId,
                ReturnType    = array.Array.QualifiedType
            };

            var marshal = new CMarshalManagedToNative(ctx)
            {
                UnboxPrimitiveValues = false
            };

            array.Array.QualifiedType.Visit(marshal);

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

            support.WriteLine("g_array_append_val({0}.array, {1});", nativeArrayId,
                              marshal.Context.Return.ToString());

            support.WriteCloseBraceIndent();

            Context.Return.Write("{0}", nativeArrayId);
            return(false);
        }
Beispiel #3
0
        public void GenerateMethodInvocation(Method method)
        {
            GenerateMethodGCHandleLookup(method);

            var paramsToMarshal    = method.Parameters.Where(p => !p.IsImplicit);
            var numParamsToMarshal = paramsToMarshal.Count();

            var argsId = "0";

            if (numParamsToMarshal > 0)
            {
                argsId = GeneratedIdentifier("args");
                WriteLine("void* {0}[{1}];", argsId, numParamsToMarshal);
            }

            var contexts = new List <MarshalContext>();

            int paramIndex = 0;

            foreach (var param in paramsToMarshal)
            {
                var ctx = new MarshalContext(Context)
                {
                    ArgName        = param.Name,
                    Parameter      = param,
                    ParameterIndex = paramIndex
                };
                contexts.Add(ctx);

                var marshal = new CMarshalNativeToManaged(ctx);
                param.QualifiedType.Visit(marshal);

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

                WriteLine("{0}[{1}] = {2};", argsId, paramIndex++,
                          marshal.Context.Return.ToString());
            }

            var exceptionId = GeneratedIdentifier("exception");

            WriteLine("MonoObject* {0} = 0;", exceptionId);

            var resultId = GeneratedIdentifier("result");

            WriteLine("MonoObject* {0};", resultId);

            var methodId   = GeneratedIdentifier("method");
            var instanceId = method.IsStatic ? "0" : GeneratedIdentifier("instance");

            WriteLine("{0} = mono_runtime_invoke({1}, {2}, {3}, &{4});", resultId,
                      methodId, instanceId, argsId, exceptionId);

            WriteLine("if ({0} != 0)", exceptionId);
            WriteStartBraceIndent();
            var errorId = GeneratedIdentifier("error");

            WriteLine("mono_m2n_error_t {0};", errorId);
            WriteLine("{0}.type = MONO_M2N_EXCEPTION_THROWN;", errorId);
            WriteLine("{0}.exception = (MonoException*) {1};", errorId, exceptionId);
            WriteLine("mono_m2n_error({0});", errorId);
            WriteCloseBraceIndent();

            foreach (var marshalContext in contexts)
            {
                if (!string.IsNullOrWhiteSpace(marshalContext.SupportAfter))
                {
                    Write(marshalContext.SupportAfter);
                }
            }
        }