static CSFile GeneratePInvokesFromTypes(TypeAggregator types, PlatformName platform, string framework) { var fileName = Path.GetFileNameWithoutExtension(framework); // /path/XamGlue.framework -> XamGlue var dylibFile = Path.Combine(framework, fileName); var funcs = TLFunctionsForFile(dylibFile, platform); var ns = new CSNamespace("SwiftRuntimeLibrary.SwiftMarshal"); var use = new CSUsingPackages(); use.And(new CSUsing("System.Runtime.InteropServices")) .And(new CSUsing("System")) .And(new CSUsing("System.Collections.Generic")) .And(new CSUsing("SwiftRuntimeLibrary")); var csFile = new CSFile(use, new CSNamespace [] { ns }); var csClass = new CSClass(CSVisibility.Internal, $"{fileName}Metadata"); new CSComment(kRobotText).AttachBefore(use); CSConditionalCompilation.If(PlatformToCSCondition(platform)).AttachBefore(use); CSConditionalCompilation.Endif.AttachAfter(ns); ns.Block.Add(csClass); var typeOntoPinvoke = new List <KeyValuePair <CSBaseExpression, CSBaseExpression> > (); var typesToProcess = new List <TypeDefinition> (); typesToProcess.AddRange(types.PublicEnums); typesToProcess.AddRange(types.PublicStructs); // pre-sort by function name typesToProcess.Sort((type1, type2) => String.CompareOrdinal(FuncIDForTypeDefinition(type1), FuncIDForTypeDefinition(type2))); foreach (var type in typesToProcess) { if (type.HasGenericParameters) { continue; } var moduleName = type.Namespace; var name = type.Name; if (TypeAggregator.FilterModuleAndName(platform, moduleName, ref name)) { var pinvoke = PInvokeForType(type, funcs); if (pinvoke != null) { csClass.Methods.Add(pinvoke); use.AddIfNotPresent(type.Namespace); var typeOf = new CSSimpleType(type.FullName).Typeof(); var funcName = pinvoke.Name; typeOntoPinvoke.Add(new KeyValuePair <CSBaseExpression, CSBaseExpression> (typeOf, funcName)); } } } var initializers = typeOntoPinvoke.Select(typeAndFunc => new CSInitializer(new CSBaseExpression [] { typeAndFunc.Key, typeAndFunc.Value }, false)); var bindingExpr = new CSInitializedType(new CSFunctionCall("Dictionary<Type, Func<SwiftMetatype>>", true), new CSInitializer(initializers, true)); var bindingDecl = new CSFieldDeclaration(new CSSimpleType("Dictionary<Type, Func<SwiftMetatype>>"), "ObjCBindingSwiftMetatypes", bindingExpr, CSVisibility.Internal, true); csClass.Fields.Add(new CSLine(bindingDecl)); use.Sort((package1, package2) => String.CompareOrdinal(package1.Package, package2.Package)); return(csFile); }
/// <summary> /// Creates a list of all types, and a hash table which is initialized on first lookup from C# type /// to Swift types. /// </summary> /// <param name="types">Aggregated types, a subset of which are included</param> /// <param name="platform">Platform targeted (typically iOS or Mac)</param> /// <param name="namespaces">Namespaces to include</param> /// <param name="framework">Name of framework used (typically XamGlue)</param> /// <returns>CSFile which, when written, has function looking up in hash table as described in summary</returns> static CSFile GenerateCSharpHashTableFromTypes(TypeAggregator types, PlatformName platform, List <string> namespaces, string framework) { var fileName = Path.GetFileNameWithoutExtension(framework); var ns = new CSNamespace("SwiftRuntimeLibrary.SwiftMarshal"); var use = new CSUsingPackages(); use.And(new CSUsing("System.Runtime.InteropServices")) .And(new CSUsing("System")) .And(new CSUsing("System.Collections.Generic")) .And(new CSUsing("SwiftRuntimeLibrary")); var csFile = new CSFile(use, new CSNamespace [] { ns }); var csClass = new CSClass(CSVisibility.Internal, $"{fileName}Metadata"); new CSComment(kRobotText).AttachBefore(use); CSConditionalCompilation.If(PlatformToCSCondition(platform)).AttachBefore(use); CSConditionalCompilation.Endif.AttachAfter(ns); ns.Block.Add(csClass); // collect all possible types, filter and sort var selectedTypes = new List <TypeDefinition> (); selectedTypes.AddRange(types.PublicEnums); selectedTypes.AddRange(types.PublicStructs); selectedTypes = selectedTypes.FindAll(type => IncludeType(type, namespaces, platform)); selectedTypes.Sort((type1, type2) => String.CompareOrdinal(type1.FullName, type2.FullName)); // add used namespaces to import list, sort list foreach (var type in selectedTypes) { use.AddIfNotPresent(type.Namespace); } use.Sort((package1, package2) => String.CompareOrdinal(package1.Package, package2.Package)); // create list of types to translate var typesForList = selectedTypes.Select(type => new CSSimpleType(type.FullName).Typeof()); var listInitializeExpr = new CSInitializedType( new CSFunctionCall("List<Type>", true), new CSInitializer(typesForList, true) ); var listBindingDecl = new CSFieldDeclaration(new CSSimpleType("List<Type>"), "csImportTypes", listInitializeExpr, CSVisibility.Internal, true); csClass.Fields.Add(new CSLine(listBindingDecl)); // create pinvoke for function var dylibFile = Path.Combine(framework, fileName); var funcs = TLFunctionsForFile(dylibFile, platform); var handleTranslationCode = new CSIdentifier(@" public static unsafe bool GetSwiftType (Type t, out SwiftMetatype md) { using (var swiftStr = new SwiftString (t.FullName)) { return SwiftCore.GetEnumMetadataByName (swiftStr.SwiftData, out md); } } internal static Dictionary<Type, SwiftMetatype> csImportMeta = null; internal static bool TryGetImportedMetadata (Type cSharpType, out SwiftMetatype md) { if (csImportMeta == null) { csImportMeta = new Dictionary<Type, SwiftMetatype> (csImportTypes.Count); foreach (var t in csImportTypes) { SwiftMetatype meta; GetSwiftType(t, out meta); csImportMeta [t] = meta; } } return csImportMeta.TryGetValue (cSharpType, out md); }" ); csClass.Fields.Add(new CSLine(handleTranslationCode, false)); return(csFile); }