public bool VisitPrimitiveType(PrimitiveType primitive) { var param = Context.Parameter; switch (primitive) { case PrimitiveType.Void: return(true); case PrimitiveType.Bool: case PrimitiveType.Char: case PrimitiveType.WideChar: case PrimitiveType.SChar: case PrimitiveType.UChar: case PrimitiveType.Short: case PrimitiveType.UShort: case PrimitiveType.Int: case PrimitiveType.UInt: case PrimitiveType.Long: case PrimitiveType.ULong: case PrimitiveType.LongLong: case PrimitiveType.ULongLong: case PrimitiveType.Float: case PrimitiveType.Double: case PrimitiveType.Decimal: case PrimitiveType.Null: { var prefix = "&"; if (IsByRefParameter || PrimitiveValuesByValue) { prefix = string.Empty; } Context.Return.Write("{0}{1}", prefix, Context.ArgName); return(true); } case PrimitiveType.String: { var argId = GenParamId(Context); var contextId = CGenerator.GenId("mono_context"); var @string = Context.ArgName; if (IsByRefParameter) { @string = $"{Context.ArgName}->str"; Context.SupportAfter.WriteLine("mono_embeddinator_marshal_string_to_gstring({0}, {1});", Context.ArgName, argId); } Context.SupportBefore.WriteLine("MonoString* {0} = ({2}) ? mono_string_new({1}.domain, {2}) : 0;", argId, contextId, @string); Context.Return.Write("{0}{1}", IsByRefParameter ? "&" : string.Empty, argId); return(true); } } throw new System.NotImplementedException(primitive.ToString()); }
public bool VisitPrimitiveType(PrimitiveType primitive) { switch (primitive) { case PrimitiveType.Void: return(true); case PrimitiveType.Bool: case PrimitiveType.WideChar: case PrimitiveType.Char: case PrimitiveType.SChar: case PrimitiveType.UChar: case PrimitiveType.Short: case PrimitiveType.UShort: case PrimitiveType.Int: case PrimitiveType.UInt: case PrimitiveType.Long: case PrimitiveType.ULong: case PrimitiveType.LongLong: case PrimitiveType.ULongLong: case PrimitiveType.Float: case PrimitiveType.Double: case PrimitiveType.Decimal: case PrimitiveType.Null: { var typePrinter = CTypePrinter; var typeName = Context.ReturnType.Visit(typePrinter); var valueId = Context.ArgName; if (UnboxPrimitiveValues) { var unboxId = CGenerator.GenId("unbox"); Context.SupportBefore.WriteLine("void* {0} = mono_object_unbox({1});", unboxId, Context.ArgName); valueId = unboxId; } Context.Return.Write("*(({0}*){1})", typeName, valueId); return(true); } case PrimitiveType.String: { var stringId = CGenerator.GenId("string"); Context.SupportBefore.WriteLine("char* {0} = mono_string_to_utf8(" + "(MonoString*) {1});", stringId, Context.ArgName); Context.Return.Write("{0}", stringId); return(true); } } throw new System.NotImplementedException(primitive.ToString()); }
public void HandleRefOutNonDefaultIntegerEnum(Enumeration @enum) { // This deals with marshaling of managed enums with non-C default // backing types (ie. enum : short). // Unlike C++ or Objective-C, C enums always have the default integer // type size, so we need to create a local variable of the right type // for marshaling with the managed runtime and cast it back to the // correct type. var backingType = @enum.BuiltinType.Type; var typePrinter = new CppTypePrinter(); var integerType = typePrinter.VisitPrimitiveType(backingType); var newArgName = CGenerator.GenId(Context.ArgName); Context.SupportBefore.WriteLine("{0} {1} = *(({0}*) {2});", integerType, newArgName, Context.ArgName); Context.Return.Write("&{0}", newArgName); Context.SupportAfter.WriteLine("*{0} = ({1}) {2};", Context.ArgName, @enum.QualifiedName, newArgName); }
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); } } }
public override string GeneratedIdentifier(string id) { return(CGenerator.GenId(id)); }
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); }
public static string GenParamId(MarshalContext ctx) { return($"{CGenerator.GenId(ctx.ArgName)}_{ctx.ParameterIndex}"); }
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); }
public static string GenParamId(Marshaler marshal) { return($"{CGenerator.GenId(marshal.ArgName)}_{marshal.ParameterIndex}"); }