コード例 #1
0
        void GenerateFieldSetter(Property property)
        {
            var setter = property.SetMethod;
            var @class = property.Namespace as Class;

            GenerateMethodSpecifier(setter, setter.Namespace as Class);
            NewLine();
            WriteStartBraceIndent();

            var field   = property.Field;
            var fieldId = GeneratedIdentifier("field");

            GenerateFieldLookup(field);

            var ctx = new MarshalContext(Context)
            {
                ArgName = "value"
            };
            var marshal = new CMarshalNativeToManaged(EmbedOptions, ctx);

            property.QualifiedType.Visit(marshal);

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

            var valueId = GeneratedIdentifier("value");

            WriteLine($"void* {valueId} = {marshal.Context.Return.ToString()};");

            if (field.IsStatic)
            {
                var vtableId = GeneratedIdentifier("vtable");
                var domainId = $"{GeneratedIdentifier("mono_context")}.domain";
                var classId  = $"class_{@class.QualifiedName}";

                WriteLine($"MonoVTable* {vtableId} = mono_class_vtable({domainId}, {classId});");
                WriteLine($"mono_field_static_set_value({vtableId}, {fieldId}, {valueId});");
            }
            else
            {
                var instanceId = GeneratedIdentifier("instance");
                var handle     = GetMonoObjectField(Options, MonoObjectFieldUsage.Instance,
                                                    FixMethodParametersPass.ObjectParameterId, "_handle");

                WriteLine($"MonoObject* {instanceId} = mono_gchandle_get_target({handle});");
                WriteLine($"mono_field_set_value({instanceId}, {fieldId}, {valueId});");
            }

            WriteCloseBraceIndent();
        }
コード例 #2
0
        public void GenerateMethodInvocation(Method method)
        {
            GenerateMethodInitialization(method);
            NewLineIfNeeded();

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

            var argsId = "0";

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

            var marshalers = new List <Marshaler>();

            int paramIndex = 0;

            foreach (var param in paramsToMarshal)
            {
                var marshal = new CMarshalNativeToManaged(Context)
                {
                    ArgName        = param.Name,
                    Parameter      = param,
                    ParameterIndex = paramIndex
                };
                marshalers.Add(marshal);

                param.Visit(marshal);

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

                WriteLine($"{argsId}[{paramIndex++}] = {marshal.Return};");
                NeedNewLine();
            }

            NewLineIfNeeded();

            var exceptionId = GeneratedIdentifier("exception");

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

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

            if (method.IsVirtual)
            {
                var virtualMethodId = GeneratedIdentifier("virtual_method");
                WriteLine($"MonoMethod* {virtualMethodId} = mono_object_get_virtual_method({instanceId}, {methodId});");
                methodId = virtualMethodId;
            }

            var @class = method.Namespace as Class;

            if (@class.IsValueType && !method.IsStatic)
            {
                var unboxedId = CGenerator.GenId("unboxed");
                WriteLine($"void* {unboxedId} = mono_object_unbox({instanceId});");
                instanceId = unboxedId;
            }

            Write($"MonoObject* {GeneratedIdentifier("result")} = ");
            WriteLine($"mono_runtime_invoke({methodId}, {instanceId}, {argsId}, &{exceptionId});");

            NewLine();
            WriteLine($"if ({exceptionId})");

            if (method.IsConstructor)
            {
                WriteLine("{");
                WriteLineIndent($"free({GeneratedIdentifier("object")});");
            }

            WriteLineIndent($"mono_embeddinator_throw_exception({exceptionId});");

            if (method.IsConstructor)
            {
                WriteLineIndent("return 0;");
                WriteLine("}");
            }

            NeedNewLine();

            foreach (var marshal in marshalers)
            {
                if (!string.IsNullOrWhiteSpace(marshal.After))
                {
                    NewLineIfNeeded();
                    Write(marshal.After);
                }
            }
        }
コード例 #3
0
        public override bool VisitManagedArrayType(ManagedArrayType array,
                                                   TypeQualifiers quals)
        {
            var support = Context.SupportBefore;

            var arrayId = CGenerator.GenId($"{Context.ArgName}_array");

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

            var arraySizeId = CGenerator.GenId($"{Context.ArgName}_array_size");

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

            var typePrinter = CTypePrinter;

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

            typePrinter.PrintScopeKind = TypePrintScopeKind.Qualified;
            var arrayElementName = array.Array.Type.Visit(typePrinter);

            if (array.Array.Type.IsClass())
            {
                arrayElementName += "*";
            }
            var elementSize = $"sizeof({arrayElementName})";

            var nativeArrayId = CGenerator.GenId($"{Context.ArgName}_native_array");

            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($"{Context.ArgName}_element_class");

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

            var elementSizeId = CGenerator.GenId($"{Context.ArgName}_array_element_size");

            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($"{Context.ArgName}_array_element");

            if (CMarshalNativeToManaged.IsValueType(array.Array.Type))
            {
                var addressId = $"mono_array_addr_with_size({arrayId}, {elementSizeId}, {iteratorId})";
                if (array.Array.Type.IsClass())
                {
                    support.WriteLine("MonoObject* {0} = mono_value_box({1}.domain, {2}, {3});",
                                      elementId, CGenerator.GenId("mono_context"), elementClassId, addressId);
                }
                else
                {
                    support.WriteLine("char* {0} = {1};",
                                      elementId, addressId);
                }
            }
            else
            {
                support.WriteLine("MonoObject* {0} = *(MonoObject**) mono_array_addr_with_size({1}, {2}, {3});",
                                  elementId, arrayId, elementSizeId, iteratorId);
            }

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

            var marshal = new CMarshalManagedToNative(Options, 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);
        }
コード例 #4
0
        public override bool VisitManagedArrayType(ManagedArrayType array,
                                                   TypeQualifiers quals)
        {
            var support = Context.SupportBefore;

            var contextId      = CGenerator.GenId("mono_context");
            var arrayId        = CGenerator.GenId($"{Context.ArgName}_array");
            var elementClassId = CGenerator.GenId($"{Context.ArgName}_element_class");

            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 isValueType = IsValueType(elementType);

            var elementSizeId = string.Empty;

            if (array.Array.Type.IsClass() && isValueType)
            {
                elementSizeId = CGenerator.GenId($"{Context.ArgName}_array_element_size");
                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}.array->len; {0}++)",
                              iteratorId, Context.ArgName);
            support.WriteStartBraceIndent();

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

            var elementId = CGenerator.GenId($"{Context.ArgName}_array_element");

            if (elementType.IsClass())
            {
                elementTypeName += "*";
                support.WriteLine("{0} {1} = g_array_index({2}.array, {0}, {3});",
                                  elementTypeName, elementId, Context.ArgName, iteratorId);
            }
            else
            {
                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(Options, ctx)
            {
                PrimitiveValuesByValue = true
            };

            elementType.Visit(marshal);

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

            if (isValueType)
            {
                if (elementType.IsClass())
                {
                    var srcId = CGenerator.GenId("src");
                    var ptrId = CGenerator.GenId("ptr");
                    support.WriteLine("char* {0} = {1};", srcId, marshal.Context.Return.ToString());
                    support.WriteLine("char* {0} = mono_array_addr_with_size({1}, {2}, {3});",
                                      ptrId, arrayId, elementSizeId, iteratorId);
                    support.WriteLine("memcpy({0}, {1}, {2});",
                                      ptrId, srcId, elementSizeId);
                }
                else
                {
                    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);
        }