/// <summary> /// Process the specified config file. /// </summary> /// <param name="file">The file.</param> private void ProcessCppModuleWithConfig(CppModule cppModule, ConfigFile file) { Logger.PushLocation(file.AbsoluteFilePath); try { CsAssembly assembly = null; if (!string.IsNullOrEmpty(file.Assembly)) { assembly = assemblyManager.GetOrCreateAssembly(file.Assembly); } if (assembly != null) { Logger.Message("Process rules for assembly [{0}] and namespace [{1}]", file.Assembly, file.Namespace); } var elementFinder = new CppElementFinder(cppModule); // Only attach includes when there is a bind to an assembly if (assembly != null) { AttachIncludes(file); ProcessExtensions(elementFinder, file); } ProcessMappings(elementFinder, file); } finally { Logger.PopLocation(); } }
public void PointerSizeReturnValueNotLarge() { var config = new ConfigFile { Id = nameof(PointerSizeReturnValueNotLarge), Namespace = nameof(PointerSizeReturnValueNotLarge), Includes = { new IncludeRule { File = "pointerSize.h", Attach = true, Namespace = nameof(PointerSizeReturnValueNotLarge) } }, Extension = { new DefineExtensionRule { Struct = "SharpGen.Runtime.PointerSize", SizeOf = 8, IsNativePrimitive = true, } }, Bindings = { new BindRule("int", "SharpGen.Runtime.PointerSize") } }; var iface = new CppInterface("Interface"); iface.Add(new CppMethod("method") { ReturnValue = new CppReturnValue { TypeName = "int" } }); var include = new CppInclude("pointerSize"); include.Add(iface); var module = new CppModule("SharpGenTestModule"); module.Add(include); var(solution, _) = MapModel(module, config); Assert.Single(solution.EnumerateDescendants <CsInterface>()); var csIface = solution.EnumerateDescendants <CsInterface>().First(); Assert.Single(csIface.Methods); var method = csIface.Methods.First(); Assert.False(method.IsReturnStructLarge); }
public void SequentialOffsets() { var config = new Config.ConfigFile { Id = nameof(SequentialOffsets), Namespace = nameof(SequentialOffsets), Includes = { new Config.IncludeRule { File = "simple.h", Attach = true, Namespace = nameof(SequentialOffsets) } }, Bindings = { new Config.BindRule("int", "System.Int32") } }; var cppStruct = new CppStruct { Name = "struct" }; cppStruct.Add(new CppField { Name = "field", TypeName = "int" }); cppStruct.Add(new CppField { Name = "field2", TypeName = "int", Offset = 1 }); var cppInclude = new CppInclude { Name = "simple" }; var cppModule = new CppModule(); cppModule.Add(cppInclude); cppInclude.Add(cppStruct); var(solution, _) = MapModel(cppModule, config); var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(); var field = csStruct.Fields.First(fld => fld.Name == "Field"); var field2 = csStruct.Fields.First(fld => fld.Name == "Field2"); Assert.Equal(0, field.Offset); Assert.Equal(4, field2.Offset); }
private CppModule ParseCpp(CastXml castXml, CppModule group) { // Run the parser var parser = new CppParser(Logger, castXml) { OutputPath = IntermediateOutputPath }; parser.Initialize(Config); if (Logger.HasErrors) { Logger.Fatal("Initializing parser failed"); } // Run the parser group = parser.Run(group); if (Logger.HasErrors) { Logger.Fatal("Parsing C++ failed."); } else { Logger.Message("Parsing C++ finished"); } // Print statistics PrintStatistics(parser); return(group); }
/// <summary> /// Prepares a transformer from C++ to C# model. /// </summary> /// <typeparam name="TCppElement">The C++ type of data to process</typeparam> /// <param name="transform">The transform.</param> /// <param name="typeToProcess">The type to process.</param> private IEnumerable <TCsElement> PrepareTransform <TCppElement, TCsElement>(CppModule cppModule, ITransformPreparer <TCppElement, TCsElement> transform) where TCppElement : CppElement where TCsElement : CsBase { var csElements = new List <TCsElement>(); // Predefine all structs, typedefs and interfaces foreach (var cppInclude in cppModule.Includes) { foreach (var cppItem in cppInclude.Iterate <TCppElement>()) { Logger.RunInContext( cppItem.ToString(), () => { // If already mapped, it means that there is already a predefined mapping if (typeRegistry.FindBoundType(cppItem.Name) == null) { var csElement = transform.Prepare(cppItem); if (csElement != null) { csElements.Add(csElement); } } }); } } return(csElements); }
public void ShortNameRuleReplacesAcronym() { var config = new ConfigFile { Id = nameof(ShortNameRuleReplacesAcronym), Namespace = nameof(ShortNameRuleReplacesAcronym), Includes = { new IncludeRule { File = "simpleStruct.h", Attach = true, Namespace = nameof(ShortNameRuleReplacesAcronym) } }, Naming = { new NamingRuleShort("DESC", "Description") } }; var cppStruct = new CppStruct("TEST_DESC"); var include = new CppInclude("simpleStruct"); include.Add(cppStruct); var module = new CppModule("SharpGenTestModule"); module.Add(include); var(solution, _) = MapModel(module, config); Assert.Single(solution.EnumerateDescendants <CsStruct>().Where(element => element.Name == "TestDescription")); }
/// <summary> /// Run CodeGenerator /// </summary> public void Run() { log.Info("Starting code generation..."); // Initialize the parser CppParser parser = new CppParser(CastXmlExecutablePath, VcToolsPath); parser.ForceParsing = configHasChanged || forceParsing; parser.Initialize(config); // Run the parser CppModule mainModule = parser.Run(); // Run the code generation process NodeJSGenerator generator = new NodeJSGenerator(config, new DriverOptions(), mainModule); // Setup rules and process code generator.SetupPasses(); generator.ProcessCode(); // Generate wrapper code List <GeneratorOutput> outputs = generator.GenerateCode(); SaveCode(outputs); }
/// <summary> /// Initializes this instance with the specified C++ module and config. /// </summary> /// <param name="cppModule">The C++ module.</param> /// <param name="config">The root config file.</param> /// <returns>The module to transform after mapping rules have been applied.</returns> private CppModule MapModule(CppModule cppModule, IEnumerable <ConfigFile> configFiles) { var numberOfConfigFilesToParse = configFiles.Count(); var indexFile = 0; // Process each config file foreach (var configFile in configFiles) { Logger.Progress(30 + (indexFile * 30) / numberOfConfigFilesToParse, "Processing mapping rules [{0}]", configFile.Assembly ?? configFile.Id); ProcessCppModuleWithConfig(cppModule, configFile); indexFile++; } // Strip out includes we aren't processing from transformation var moduleToTransform = new CppModule { Name = cppModule.Name }; foreach (var include in cppModule.Includes.Where(cppInclude => _includesToProcess.Contains(cppInclude.Name)).ToArray()) { moduleToTransform.Add(include); } return(moduleToTransform); }
/// <summary> /// Apply documentation from an external provider. This is optional. /// </summary> /// <param name="cache">The cache of doc items.</param> /// <param name="group">The module to document.</param> private Task <CppModule> ApplyDocumentation(DocItemCache cache, CppModule group) { IDocProvider docProvider = null; // Try to load doc provider from an external assembly if (DocProviderAssemblyPath != null) { try { var assembly = Assembly.LoadFrom(DocProviderAssemblyPath); foreach (var type in assembly.GetTypes()) { if (typeof(IDocProvider).GetTypeInfo().IsAssignableFrom(type)) { docProvider = (IDocProvider)Activator.CreateInstance(type); break; } } } catch (Exception) { Logger.Warning(null, "Warning, Unable to locate/load DocProvider Assembly."); Logger.Warning(null, "Warning, DocProvider was not found from assembly [{0}]", DocProviderAssemblyPath); } } if (docProvider == null) { return(Task.FromResult(group)); } Logger.Progress(20, "Applying C++ documentation"); return(docProvider.ApplyDocumentation(cache, group)); }
public void Simple() { var config = new Config.ConfigFile { Id = nameof(Simple), Namespace = nameof(Simple), Assembly = nameof(Simple), Includes = { new Config.IncludeRule { File = "simple.h", Attach = true, Namespace = nameof(Simple) } }, Bindings = { new Config.BindRule("int", "System.Int32") } }; var cppStruct = new CppStruct { Name = "struct" }; cppStruct.Add(new CppField { Name = "field", TypeName = "int" }); var cppInclude = new CppInclude { Name = "simple" }; var cppModule = new CppModule(); cppModule.Add(cppInclude); cppInclude.Add(cppStruct); var(solution, _) = MapModel(cppModule, config); Assert.Single(solution.EnumerateDescendants().OfType <CsStruct>()); var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(); Assert.Single(csStruct.Fields.Where(fld => fld.Name == "Field")); var field = csStruct.Fields.First(fld => fld.Name == "Field"); Assert.IsType <CsFundamentalType>(field.PublicType); var fundamental = (CsFundamentalType)field.PublicType; Assert.Equal(typeof(int), fundamental.Type); }
public ASTConverter(BindingContext bindingContext, ConfigMapping configurationContext, CppModule moduleContext) { this.configurationContext = configurationContext; this.bindingContext = bindingContext; this.moduleContext = moduleContext; cppElementToDeclarationMapping = new Dictionary <CppElement, Declaration>(); }
public void Simple() { var config = new ConfigFile { Id = nameof(Simple), Namespace = nameof(Simple), Includes = { new IncludeRule { File = "interface.h", Attach = true, Namespace = nameof(Simple) } }, Bindings = { new BindRule("int", "System.Int32") } }; var iface = new CppInterface("Interface") { TotalMethodCount = 1 }; iface.Add(new CppMethod("method") { ReturnValue = new CppReturnValue { TypeName = "int" } }); var include = new CppInclude("interface"); include.Add(iface); var module = new CppModule("SharpGenTestModule"); module.Add(include); var(solution, _) = MapModel(module, config); Assert.Single(solution.EnumerateDescendants().OfType <CsInterface>()); var csIface = solution.EnumerateDescendants().OfType <CsInterface>().First(); Assert.Single(csIface.Methods); var method = csIface.Methods.First(); Assert.Equal(0, method.Offset); Assert.IsType <CsFundamentalType>(method.ReturnValue.PublicType); Assert.Equal(TypeRegistry.Int32, method.ReturnValue.PublicType); }
public void IntFieldMappedToBoolIsMarkedAsBoolToInt() { var structName = "BoolToInt"; var config = new ConfigFile { Id = nameof(IntFieldMappedToBoolIsMarkedAsBoolToInt), Namespace = nameof(IntFieldMappedToBoolIsMarkedAsBoolToInt), Includes = { new IncludeRule { File = "test.h", Attach = true, Namespace = nameof(IntFieldMappedToBoolIsMarkedAsBoolToInt) } }, Bindings = { new BindRule("int", "System.Int32"), new BindRule("bool", "System.Boolean") }, Mappings = { new MappingRule { Field = $"{structName}::field", MappingType = "bool", }, } }; var structure = new CppStruct(structName); structure.Add(new CppField("field") { TypeName = "int" }); var include = new CppInclude("test"); include.Add(structure); var module = new CppModule("SharpGenTestModule"); module.Add(include); var(solution, _) = MapModel(module, config); Assert.Single(solution.EnumerateDescendants().OfType <CsStruct>().Where(csStruct => csStruct.Name == structName)); var generatedStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(csStruct => csStruct.Name == structName); Assert.Single(generatedStruct.Fields); var field = generatedStruct.Fields.First(); Assert.True(field.IsBoolToInt); }
public void InheritingStructs() { var config = new ConfigFile { Id = nameof(InheritingStructs), Namespace = nameof(InheritingStructs), Includes = { new IncludeRule { File = "struct.h", Attach = true, Namespace = nameof(SequentialOffsets) } }, Bindings = { new BindRule("int", "System.Int32") } }; var baseStruct = new CppStruct("base"); baseStruct.Add(new CppField("field") { TypeName = "int" }); var inheritingStruct = new CppStruct("inheriting") { Base = "base" }; inheritingStruct.Add(new CppField("field2") { TypeName = "int", Offset = 1 }); var cppInclude = new CppInclude("struct"); var cppModule = new CppModule("SharpGenTestModule"); cppModule.Add(cppInclude); cppInclude.Add(baseStruct); cppInclude.Add(inheritingStruct); var(solution, _) = MapModel(cppModule, config); var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(@struct => @struct.Name == "Inheriting"); var field = csStruct.Fields.First(fld => fld.Name == "Field"); var field2 = csStruct.Fields.First(fld => fld.Name == "Field2"); Assert.Equal(0u, field.Offset); Assert.Equal(4u, field2.Offset); }
public void MappingNameRuleRenamesStructMember() { var config = new Config.ConfigFile { Id = nameof(MappingNameRuleRenamesStructMember), Namespace = nameof(MappingNameRuleRenamesStructMember), Assembly = nameof(MappingNameRuleRenamesStructMember), Includes = { new Config.IncludeRule { File = "simpleStruct.h", Attach = true, Namespace = nameof(MappingNameRuleRenamesStructMember) } }, Bindings = { new Config.BindRule("int", "System.Int32") }, Mappings = { new Config.MappingRule { Field = "Test::field", MappingName = "MyField" } } }; var cppStruct = new CppStruct { Name = "Test" }; cppStruct.Add(new CppField { Name = "field", TypeName = "int" }); var include = new CppInclude { Name = "simpleStruct" }; include.Add(cppStruct); var module = new CppModule(); module.Add(include); var(solution, _) = MapModel(module, config); var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(element => element.Name == "Test"); Assert.Single(csStruct.Fields.Where(field => field.Name == "MyField")); }
public void RemoveParentDoesNotRemoveAllParents() { var config = new Config.ConfigFile { Id = nameof(RemoveParentDoesNotRemoveAllParents), Assembly = nameof(RemoveParentDoesNotRemoveAllParents), Namespace = nameof(RemoveParentDoesNotRemoveAllParents), Includes = { new Config.IncludeRule { Attach = true, File = "cppEnum.h", Namespace = nameof(RemoveParentDoesNotRemoveAllParents) } }, Mappings = { new Config.RemoveRule { Method = @"#.*ToRemove" } } }; var cppModel = new CppModule(); var cppInclude = new CppInclude { Name = "cppEnum" }; var cppIface = new CppInterface { Name = "TestInterface" }; cppInclude.Add(cppIface); var cppMethod = new CppMethod { Name = "Method" }; cppMethod.Add(new CppParameter { Name = "ParamToRemove" }); cppModel.Add(cppInclude); var(solution, _) = MapModel(cppModel, config); var members = solution.EnumerateDescendants(); Assert.NotEmpty(members.OfType <CsInterface>()); Assert.Empty(members.OfType <CsParameter>()); }
public void DualCallbackFlowsNativeImplementation() { var config = new ConfigFile { Id = nameof(Simple), Namespace = nameof(Simple), Includes = { new IncludeRule { File = "interface.h", Attach = true, Namespace = nameof(Simple) } }, Bindings = { new BindRule("int", "System.Int32") }, Mappings = { new MappingRule { Interface = "Interface", IsCallbackInterface = true, IsDualCallbackInterface = true } } }; var iface = new CppInterface("Interface") { TotalMethodCount = 1 }; iface.Add(new CppMethod("method") { ReturnValue = new CppReturnValue { TypeName = "int" } }); var include = new CppInclude("interface"); include.Add(iface); var module = new CppModule("SharpGenTestModule"); module.Add(include); var(_, defines) = GetConsumerBindings(module, config); var interfaceDefine = defines.First(define => define.Interface == "Simple.Interface"); Assert.Equal("Simple.InterfaceNative", interfaceDefine.NativeImplementation); }
public void UnionsWithPointersGeneratesStructure() { var config = new ConfigFile { Id = nameof(UnionsWithPointersGeneratesStructure), Namespace = nameof(UnionsWithPointersGeneratesStructure), Includes = { new IncludeRule { File = "test.h", Attach = true, Namespace = nameof(UnionsWithPointersGeneratesStructure) } }, Bindings = { new BindRule("int", "System.Int32") } }; var structure = new CppStruct("Test") { IsUnion = true }; structure.Add(new CppField("pointer") { TypeName = "int", Pointer = "*" }); structure.Add(new CppField("scalar") { TypeName = "int" }); var include = new CppInclude("test"); include.Add(structure); var module = new CppModule("SharpGenTestModule"); module.Add(include); var(solution, _) = MapModel(module, config); var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(); foreach (var field in csStruct.Fields) { Assert.Equal(0u, field.Offset); } Assert.False(Logger.HasErrors); }
public void ContextRuleLimitsWhereMappingRuleExecutes() { var config = new ConfigFile { Id = nameof(ContextRuleLimitsWhereMappingRuleExecutes), Namespace = nameof(ContextRuleLimitsWhereMappingRuleExecutes), Includes = { new IncludeRule { Attach = true, File = "cppEnum.h", Namespace = nameof(ContextRuleLimitsWhereMappingRuleExecutes) }, new IncludeRule { Attach = true, File = "secondFile.h", Namespace = nameof(ContextRuleLimitsWhereMappingRuleExecutes) } }, Mappings = { new Config.ContextRule("cppEnum"), new MappingRule { Enum = "AnotherEnum", MappingNameFinal = "NewEnum" }, new ClearContextRule() } }; var cppModel = new CppModule("SharpGenTestModule"); var cppInclude = new CppInclude("cppEnum"); var cppEnum = new CppEnum("TestEnum"); var secondInclude = new CppInclude("secondFile"); var cppEnum2 = new CppEnum("AnotherEnum"); cppEnum.AddEnumItem("Element1", "0"); cppEnum.AddEnumItem("Element2", "1"); cppInclude.Add(cppEnum); cppModel.Add(cppInclude); var(solution, _) = MapModel(cppModel, config); Assert.Empty(solution.EnumerateDescendants().OfType <CsEnum>().Where(csEnum => csEnum.Name == "AnotherEnum")); }
/// <summary> /// Runs this instance. /// </summary> /// <returns></returns> public CppModule Run(CppModule groupSkeleton, string[] additionalCompilationArguments) { _group = groupSkeleton; Logger.Message("Config files changed."); const string progressMessage = "Parsing C++ headers starts, please wait..."; StreamReader xmlReader = null; try { Logger.Progress(15, progressMessage); var configRootHeader = Path.Combine(OutputPath, _configRoot.Id + ".h"); xmlReader = _gccxml.Process(configRootHeader, additionalCompilationArguments); if (xmlReader != null) { Parse(xmlReader); } Logger.Progress(30, progressMessage); } catch (Exception ex) { Logger.Error(null, "Unexpected error", ex); } finally { xmlReader?.Dispose(); // Write back GCCXML document on the disk using (var stream = File.OpenWrite(Path.Combine(OutputPath, GccXmlFileName))) { GccXmlDoc?.Save(stream); } Logger.Message("Parsing headers is finished."); } // Track number of included macros for statistics foreach (var cppInclude in _group.Includes) { IncludeMacroCounts.TryGetValue(cppInclude.Name, out int count); foreach (var cppDefine in cppInclude.Macros) { count++; } IncludeMacroCounts[cppInclude.Name] = count; } return(_group); }
public BindingContext(ConfigMapping configurationContext, DriverOptions driverOptions, CppModule moduleContext) : base(driverOptions) { ConfigurationContext = configurationContext; ParserContext = moduleContext; Options = driverOptions; FoundEnums = new SortedList(); ASTConverter converter = new ASTConverter(this, configurationContext, moduleContext); ASTContext = converter.Convert(); }
public static void ExpandDynamicVariables(this ConfigFile config, Logger logger, CppModule module) { // Load all defines and store them in the config file to allow dynamic variable substitution foreach (var cppInclude in module.Includes) { foreach (var cppDefine in cppInclude.Macros) { config.DynamicVariables[cppDefine.Name] = cppDefine.Value; } } // Expand all variables with all dynamic variables config.ExpandVariables(true, logger); }
public void Enum() { var config = new Config.ConfigFile { Id = nameof(Enum), Assembly = nameof(Enum), Namespace = nameof(Enum), Includes = { new Config.IncludeRule { Attach = true, File = "cppEnum.h", Namespace = nameof(Enum) } }, Mappings = { new Config.RemoveRule { Enum = @".*ToRemove\d+" } } }; var cppModel = new CppModule(); var cppInclude = new CppInclude { Name = "cppEnum" }; var cppEnum = new CppEnum { Name = "TestEnum" }; cppInclude.Add(cppEnum); cppInclude.Add(new CppEnum { Name = "EnumToRemove1" }); cppModel.Add(cppInclude); var(solution, _) = MapModel(cppModel, config); var members = solution.EnumerateDescendants(); Assert.Single(members.OfType <CsEnum>()); }
public void ExplicitValues() { var config = new Config.ConfigFile { Id = nameof(ExplicitValues), Assembly = nameof(ExplicitValues), Namespace = nameof(ExplicitValues), Includes = { new Config.IncludeRule { Attach = true, File = "cppEnum.h", Namespace = nameof(ExplicitValues) } } }; var cppModel = new CppModule(); var cppInclude = new CppInclude { Name = "cppEnum" }; var cppEnum = new CppEnum { Name = "TestEnum" }; cppEnum.AddEnumItem("Element1", "10"); cppEnum.AddEnumItem("Element2", "15"); cppEnum.AddEnumItem("Element3", "10"); cppInclude.Add(cppEnum); cppModel.Add(cppInclude); var(solution, _) = MapModel(cppModel, config); var members = solution.EnumerateDescendants(); Assert.Single(members.OfType <CsEnum>()); var csEnum = members.OfType <CsEnum>().First(); Assert.Single(csEnum.EnumItems.Where(item => item.Name == "Element1" && item.Value == "10")); Assert.Single(csEnum.EnumItems.Where(item => item.Name == "Element2" && item.Value == "15")); Assert.Single(csEnum.EnumItems.Where(item => item.Name == "Element3" && item.Value == "10")); Assert.Equal(typeof(int), csEnum.UnderlyingType.Type); }
private (IDocumentationLinker doc, CsSolution solution) ExecuteMappings(CppModule group, ConfigFile consumerConfig) { var docLinker = new DocumentationLinker(); var typeRegistry = new TypeRegistry(Logger, docLinker); var namingRules = new NamingRulesManager(); var assemblyManager = new AssemblyManager(); // Run the main mapping process var transformer = new TransformManager( GlobalNamespace, namingRules, Logger, typeRegistry, docLinker, new ConstantManager(namingRules, docLinker), assemblyManager) { ForceGenerator = _isAssemblyNew }; var(solution, defines) = transformer.Transform(group, Config, IntermediateOutputPath); consumerConfig.Extension = new List <ExtensionBaseRule>(defines); var(bindings, generatedDefines) = transformer.GenerateTypeBindingsForConsumers(); consumerConfig.Bindings.AddRange(bindings); consumerConfig.Extension.AddRange(generatedDefines); consumerConfig.Mappings.AddRange( docLinker.GetAllDocLinks().Select( link => new MappingRule { DocItem = link.cppName, MappingNameFinal = link.cSharpName })); if (Logger.HasErrors) { Logger.Fatal("Executing mapping rules failed"); } PrintStatistics(assemblyManager); DumpRenames(transformer); return(docLinker, solution); }
public void Simple() { var config = new ConfigFile { Id = nameof(Simple), Namespace = nameof(Simple), Includes = { new IncludeRule { File = "simple.h", Attach = true, Namespace = nameof(Simple) } }, Bindings = { new BindRule("int", "System.Int32") } }; var cppStruct = new CppStruct("struct"); cppStruct.Add(new CppField("field") { TypeName = "int" }); var cppInclude = new CppInclude("simple"); var cppModule = new CppModule("SharpGenTestModule"); cppModule.Add(cppInclude); cppInclude.Add(cppStruct); var(solution, _) = MapModel(cppModule, config); Assert.Single(solution.EnumerateDescendants().OfType <CsStruct>()); var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(); Assert.Single(csStruct.Fields.Where(fld => fld.Name == "Field")); var field = csStruct.Fields.First(fld => fld.Name == "Field"); Assert.IsType <CsFundamentalType>(field.PublicType); Assert.Equal(TypeRegistry.Int32, field.PublicType); }
public void MappingNameRuleRenamesStruct() { var config = new ConfigFile { Id = nameof(MappingNameRuleRenamesStruct), Namespace = nameof(MappingNameRuleRenamesStruct), Includes = { new IncludeRule { File = "simpleStruct.h", Attach = true, Namespace = nameof(MappingNameRuleRenamesStruct) } }, Bindings = { new BindRule("int", "System.Int32") }, Mappings = { new MappingRule { Struct = "Test", MappingName = "MyStruct" } } }; var cppStruct = new CppStruct("Test"); cppStruct.Add(new CppField("field") { TypeName = "int" }); var include = new CppInclude("simpleStruct"); include.Add(cppStruct); var module = new CppModule("SharpGenTestModule"); module.Add(include); var(solution, _) = MapModel(module, config); Assert.Single(solution.EnumerateDescendants <CsStruct>().Where(element => element.Name == "MyStruct")); }
/// <summary> /// Runs this instance. /// </summary> /// <returns></returns> public CppModule Run() { // If config is updated, we need to run the if (masterConfigHasChanged) { log.Info("Config files changed."); StreamReader xmlReader = null; try { xmlReader = castXML.Process(masterHeaderFile); if (xmlReader != null) { Parse(xmlReader); } // Save back the C++ parsed includes masterCppModule.Write(MasterModuleFileName); } catch (Exception ex) { log.Error("Unexpected error", ex); } finally { if (xmlReader != null) { xmlReader.Close(); } // Write back GCCXML document on the disk if (CastXmlDoc != null) { CastXmlDoc.Save(CastXmlFileName); } log.Info("Parsing headers is finished."); } } else { masterCppModule = CppModule.Read(MasterModuleFileName); } return(masterCppModule); }
public static CppModule CreateSkeletonModule(this ConfigFile config) { var module = new CppModule(config.Id); foreach (var includeRule in config.ConfigFilesLoaded.SelectMany(cfg => cfg.Includes)) { var cppInclude = module.FindInclude(includeRule.Id); if (cppInclude != null) { continue; } module.Add(new CppInclude(includeRule.Id)); } return(module); }
/// <summary> /// Runs this instance. /// </summary> /// <returns></returns> public CppModule Run(CppModule groupSkeleton, StreamReader xmlReader) { _group = groupSkeleton; Logger.Message("Config files changed."); const string progressMessage = "Parsing C++ headers starts, please wait..."; try { Logger.Progress(15, progressMessage); if (xmlReader != null) { Parse(xmlReader); } Logger.Progress(30, progressMessage); } catch (Exception ex) { Logger.Error(null, "Unexpected error", ex); } finally { // Write back GCCXML document on the disk using (var stream = File.OpenWrite(GccXmlFileName)) { GccXmlDoc?.Save(stream); } Logger.Message("Parsing headers is finished."); } // Track number of included macros for statistics foreach (var cppInclude in _group.Includes) { IncludeMacroCounts.TryGetValue(cppInclude.Name, out var count); count += cppInclude.Macros.Count(); IncludeMacroCounts[cppInclude.Name] = count; } return(_group); }