bool HandleSpecialCILType(CILType cilType) { var type = cilType.Type; if (type == typeof(string)) { var argId = CGenerator.GenId(Context.ArgName); var contextId = CGenerator.GenId("mono_context"); var stringText = Context.ArgName; var param = Context.Parameter; var isByRef = param != null && (param.IsOut || param.IsInOut); if (isByRef) { stringText = string.Format("({0}->len != 0) ? {0}->str : \"\"", Context.ArgName); Context.SupportAfter.WriteLine("g_string_truncate({0}, 0);", Context.ArgName); Context.SupportAfter.WriteLine("g_string_append({0}, mono_string_to_utf8(" + "(MonoString*) {1}));", Context.ArgName, argId); } Context.SupportBefore.WriteLine("MonoString* {0} = mono_string_new({1}.domain, {2});", argId, contextId, stringText); Context.Return.Write("{0}{1}", isByRef ? "&" : string.Empty, argId); return(true); } return(false); }
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.LongDouble: case PrimitiveType.Null: { var prefix = "&"; if ((param != null && (param.IsInOut || param.IsOut)) || PrimitiveValuesByValue) { prefix = string.Empty; } Context.Return.Write("{0}{1}", prefix, Context.ArgName); return(true); } case PrimitiveType.String: { var argId = $"{CGenerator.GenId(Context.ArgName)}_{Context.ParameterIndex}"; var contextId = CGenerator.GenId("mono_context"); var @string = Context.ArgName; var isByRef = param != null && (param.IsOut || param.IsInOut); if (isByRef) { @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}", isByRef ? "&" : string.Empty, argId); return(true); } } throw new System.NotImplementedException(primitive.ToString()); }
public JavaGenerator(BindingContext context) : base(context) { TypePrinter = new JavaTypePrinter(Context); Passes = new PassBuilder <TranslationUnitPass>(Context); CGenerator.SetupPasses(Passes); }
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 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"); 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()); 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; }
public override bool VisitClassDecl(Class @class) { var instanceId = CGenerator.GenId($"{Context.ArgName}_instance"); var handle = CSources.GetMonoObjectField(Options, Context.ArgName, "_handle"); Context.SupportBefore.WriteLine($"MonoObject* {instanceId} = mono_gchandle_get_target({handle});"); Context.Return.Write("{0}", instanceId); return(true); }
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.LongDouble: 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 static string GenerateArrayTypeLookup(Type type, TextGenerator gen) { type = type.Desugar(); if (type is BuiltinType) { var builtinType = type as BuiltinType; return(GetMonoClassForPrimitiveType(builtinType.Type)); } else if (type is CILType) { var cilType = type as CILType; if (cilType.Type == typeof(string)) { return("mono_get_string_class()"); } return(string.Format("mono_embeddinator_search_class(\"{0}\", \"{1}\", \"{2}\")", cilType.Type.Assembly.GetName().Name, cilType.Type.Namespace, cilType.Type.Name)); } else if (type is TagType) { var tagType = type as TagType; var decl = tagType.Declaration; var @namespace = string.Empty; var ids = string.Join(", ", decl.QualifiedName.Split('.').Select(n => $"\"{n}\"")); var unit = decl.TranslationUnit; var classId = $"class_{decl.QualifiedName}"; var monoImageName = $"{CGenerator.AssemblyId(unit)}_image"; gen.WriteLine("{0} = mono_class_from_name({1}, \"{2}\", \"{3}\");", classId, monoImageName, @namespace, decl.ManagedQualifiedName()); return(classId); } else if (type is ArrayType) { var arrayType = type as ArrayType; return("0"); } throw new System.NotImplementedException(); }
bool HandleSpecialCILType(CILType cilType) { var type = cilType.Type; if (type == typeof(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); } return(false); }
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 GenerateAssemblyLoad() { var assemblyName = Unit.FileName; var assemblyLookupId = GeneratedIdentifier($"lookup_assembly_{assemblyName.Replace('.', '_')}"); PushBlock(); WriteLine($"static void {assemblyLookupId}()"); WriteStartBraceIndent(); var monoImageName = string.Format("{0}_image", CGenerator.AssemblyId(Unit)); WriteLine("if ({0})", monoImageName); WriteLineIndent("return;"); WriteLine("{0} = mono_embeddinator_load_assembly(&{1}, \"{2}\");", monoImageName, GeneratedIdentifier("mono_context"), assemblyName); WriteCloseBraceIndent(); PopBlock(NewLineKind.BeforeNextBlock); }
public override void Process() { RemoveTypedefNodes(); GenerateFilePreamble(CommentKind.BCPL, "Embeddinator-4000"); PushBlock(); WriteHeaders(); PopBlock(NewLineKind.BeforeNextBlock); PushBlock(); WriteLine("mono_embeddinator_context_t {0};", GeneratedIdentifier("mono_context")); WriteLine("MonoImage* {0}_image;", CGenerator.AssemblyId(Unit)); PopBlock(NewLineKind.BeforeNextBlock); GenerateObjectDeclarations(); GenerateGlobalMethods(); VisitDeclContext(Unit); }
public static string GenerateMonoClassFromNameCall(Declaration decl) { var namespaces = Declaration.GatherNamespaces(decl.Namespace) .Where(ns => !(ns is TranslationUnit)); var @namespace = string.Join(".", namespaces); var ids = string.Join(", ", decl.QualifiedName.Split('.').Select(n => string.Format("\"{0}\"", n))); var monoImageName = string.Format("{0}_image", CGenerator.AssemblyId(decl.TranslationUnit)); var managedName = decl.ManagedQualifiedName(); var dotIndex = managedName.LastIndexOf(".", StringComparison.Ordinal); if (dotIndex > 0) { managedName = managedName.Substring(managedName.LastIndexOf(".", StringComparison.Ordinal) + 1); } return($"mono_class_from_name({monoImageName}, \"{@namespace}\", \"{managedName}\");"); }
public void GenerateNativeDeclarations(TranslationUnit unit) { // Since the native declarations are targetting the generated C bindings, // we need to modify the AST to match the one generated by the C target. var passes = new PassBuilder <TranslationUnitPass>(Context); CGenerator.SetupPasses(passes); Context.Options.GeneratorKind = GeneratorKind.C; passes.RunPasses(pass => { pass.Context = Context; pass.VisitASTContext(Context.ASTContext); }); Context.Options.GeneratorKind = GeneratorKind.Java; var nativeGen = new JavaNative(Context, unit); Generators.Add(nativeGen); }
public void GenerateMethodInvocation(Method method) { GenerateMethodInitialization(method); NewLine(); 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 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(EmbedOptions, ctx); param.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) { Write(marshal.Context.SupportBefore); } WriteLine($"{argsId}[{paramIndex++}] = {marshal.Context.Return};"); } var exceptionId = GeneratedIdentifier("exception"); WriteLine($"MonoObject* {exceptionId} = 0;"); var resultId = GeneratedIdentifier("result"); WriteLine($"MonoObject* {resultId};"); 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; } WriteLine("{0} = mono_runtime_invoke({1}, {2}, {3}, &{4});", resultId, methodId, instanceId, argsId, exceptionId); NewLine(); WriteLine($"if ({exceptionId})"); WriteStartBraceIndent(); if (method.IsConstructor) { WriteLine("free(object);"); } WriteLine($"mono_embeddinator_throw_exception({exceptionId});"); if (method.IsConstructor) { WriteLine("return 0;"); } WriteCloseBraceIndent(); foreach (var marshalContext in contexts) { if (!string.IsNullOrWhiteSpace(marshalContext.SupportAfter)) { Write(marshalContext.SupportAfter); } } }
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); 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"); 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(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}"); }