public override bool VisitCppStruct(CppStruct cppStruct) { Declaration unitDecl; cppElementToDeclarationMapping.TryGetValue(cppStruct.ParentInclude, out unitDecl); TranslationUnit unit = unitDecl != null ? unitDecl as TranslationUnit : FindDeclParent <TranslationUnit>(cppStruct.ParentInclude); Namespace @namespace = null; Class @structAsClass = null; // Check if we have an namespace if (!string.IsNullOrEmpty(cppStruct.Namespace)) { @namespace = unit.FindCreateNamespace(cppStruct.Namespace.TrimStart(':')); @structAsClass = @namespace.FindClass(cppStruct.Name, true, true); } else { @structAsClass = unit.FindClass(cppStruct.Name, true, true); } @structAsClass.Type = ClassType.ValueType; cppElementToDeclarationMapping.Add(cppStruct, @structAsClass); return(base.VisitCppStruct(cppStruct)); }
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); }
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")); }
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 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 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 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 CsStruct(CppStruct cppStruct) { IsIn = true; IsOut = false; CppElement = cppStruct; // Align was not overloaded by MappingRule tag, then we can take the default value if (cppStruct != null && Align == 0) { Align = cppStruct.Align; } }
// Use this for initialization void Start() { int x = 0; x = add(10, 20); Debug.Log(x); CppStruct info = new CppStruct(); getStructData(ref info); Debug.Log(info.a); }
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 CsStruct(CppStruct cppStruct, string name) : base(cppStruct, name) { if (cppStruct == null) { return; } var tag = cppStruct.Rule; Align = tag.StructPack ?? Align; HasMarshalType = tag.StructHasNativeValueType ?? HasMarshalType; GenerateAsClass = tag.StructToClass ?? GenerateAsClass; HasCustomMarshal = tag.StructCustomMarshal ?? HasCustomMarshal; IsStaticMarshal = tag.IsStaticMarshal ?? IsStaticMarshal; HasCustomNew = tag.StructCustomNew ?? HasCustomNew; }
public CsStruct(CppStruct cppStruct, string name, MappingRule tag = null) : base(cppStruct, name) { tag ??= cppStruct?.Rule; Align = tag?.StructPack ?? Align; HasMarshalType = tag?.StructHasNativeValueType ?? HasMarshalType; GenerateAsClass = tag?.StructToClass ?? GenerateAsClass; HasCustomMarshal = tag?.StructCustomMarshal ?? HasCustomMarshal; IsStaticMarshal = tag?.IsStaticMarshal ?? IsStaticMarshal; HasCustomNew = tag?.StructCustomNew ?? HasCustomNew; if (HasCustomMarshal || IsStaticMarshal || HasCustomNew || GenerateAsClass) { HasMarshalType = true; } }
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> /// Parses a C++ struct or union declaration. /// </summary> private CppStruct ParseStructOrUnion(XElement xElement, CppElement cppParent = null, int innerAnonymousIndex = 0) { CppStruct cppStruct = xElement.Annotation <CppStruct>(); if (cppStruct != null) { return(cppStruct); } // Build struct name directly from the struct name or based on the parent string structName = String.Empty; XAttribute structNameAttribute = xElement.Attribute("name"); if (structNameAttribute != null) { structName = structNameAttribute.Value; } if (cppParent != null) { if (string.IsNullOrEmpty(structName)) { structName = cppParent.Name + "_Inner_" + innerAnonymousIndex; } else { structName = cppParent.Name + "_" + structName + "_Inner"; } } // Create struct cppStruct = new CppStruct { Name = structName }; xElement.AddAnnotation(cppStruct); bool isUnion = (xElement.Name.LocalName == StringEnum.GetStringValue(CastXMLTag.Union)); // Get align from structure cppStruct.Align = xElement.Attribute("align") != null?int.Parse(xElement.Attribute("align").Value) / 8 : 0; // Enter struct/union description var basesValueAttribute = xElement.Attribute("bases"); IEnumerable <string> bases = basesValueAttribute != null?basesValueAttribute.Value.Split(' ') : Enumerable.Empty <string>(); foreach (string xElementBaseId in bases) { if (string.IsNullOrEmpty(xElementBaseId)) { continue; } XElement xElementBase = mapIdToXElement[xElementBaseId]; CppStruct cppStructBase = ParseStructOrUnion(xElementBase); if (string.IsNullOrEmpty(cppStructBase.ParentName)) { cppStruct.ParentName = cppStructBase.Name; } } // Parse all fields int fieldOffset = 0; int innerStructCount = 0; foreach (XElement field in xElement.Elements()) { if (field.Name.LocalName != StringEnum.GetStringValue(CastXMLTag.Field)) { continue; } // Parse the field var cppField = ParseField(field); cppField.Offset = fieldOffset; // Test if the field type is declared inside this struct or union string fieldName = field.Attribute("name") != null?field.Attribute("name").Value : String.Empty; string fieldTypeId = field.Attribute("type") != null?field.Attribute("type").Value : String.Empty; XElement fieldType = mapIdToXElement[fieldTypeId]; string fieldTypeContext = fieldType.Attribute("context") != null?fieldType.Attribute("context").Value : String.Empty; string fieldId = field.Attribute("id") != null?field.Attribute("id").Value : String.Empty; if (fieldTypeContext == fieldId) { var fieldSubStruct = ParseStructOrUnion(fieldType, cppStruct, innerStructCount++); // If fieldName is empty, then we need to inline fields from the struct/union. if (string.IsNullOrEmpty(fieldName)) { // Make a copy in order to remove fields List <CppField> listOfSubFields = new List <CppField>(fieldSubStruct.Fields); // Copy the current field offset int lastFieldOffset = fieldOffset; foreach (CppField subField in listOfSubFields) { subField.Offset = subField.Offset + fieldOffset; cppStruct.Add(subField); lastFieldOffset = subField.Offset; } // Set the current field offset according to the inlined fields if (!isUnion) { fieldOffset = lastFieldOffset; } // Don't add the current field, as it is actually an inline struct/union cppField = null; } else { // Get the type name from the inner-struct and set it to the field cppField.TypeName = fieldSubStruct.Name; currentCppInclude.Add(fieldSubStruct); } } // Go to next field offset if not in union bool goToNextFieldOffset = !isUnion; // Add the field if any if (cppField != null) { cppStruct.Add(cppField); // TODO managed multiple bitfield group // Current implem is only working with a single set of consecutive bitfield in the same struct goToNextFieldOffset = goToNextFieldOffset && !cppField.IsBitField; } if (goToNextFieldOffset) { fieldOffset++; } } return(cppStruct); }
public void NonPortableLayoutDoesNotErrorWhenMarkedForCustomMarshalling() { var config = new ConfigFile { Id = nameof(NonPortableLayoutDoesNotErrorWhenMarkedForCustomMarshalling), Namespace = nameof(NonPortableLayoutDoesNotErrorWhenMarkedForCustomMarshalling), Includes = { new IncludeRule { File = "test.h", Attach = true, Namespace = nameof(NonPortableLayoutDoesNotErrorWhenMarkedForCustomMarshalling) } }, Bindings = { new BindRule("int", "System.Int32") }, Mappings = { new MappingRule { Struct = "Test", StructCustomMarshal = true } } }; var structure = new CppStruct("Test"); structure.Add(new CppField("bitfield1") { TypeName = "int", IsBitField = true, BitOffset = 16, Offset = 0, }); structure.Add(new CppField("bitfield2") { TypeName = "int", IsBitField = true, BitOffset = 16, Offset = 0 }); structure.Add(new CppField("pointer") { TypeName = "int", Pointer = "*", Offset = 1 }); structure.Add(new CppField("field") { TypeName = "int", Offset = 2, }); var include = new CppInclude("test"); include.Add(structure); var module = new CppModule("SharpGenTestModule"); module.Add(include); var(solution, _) = MapModel(module, config); Assert.False(Logger.HasErrors); }
public CsStruct(CppStruct cppStruct) { CppElement = cppStruct; }
public void NonPortableStructAlignmentRaisesError() { var config = new ConfigFile { Id = nameof(NonPortableStructAlignmentRaisesError), Namespace = nameof(NonPortableStructAlignmentRaisesError), Includes = { new IncludeRule { File = "test.h", Attach = true, Namespace = nameof(NonPortableStructAlignmentRaisesError) } }, Bindings = { new BindRule("int", "System.Int32") } }; var structure = new CppStruct("Test"); structure.Add(new CppField("bitfield1") { TypeName = "int", IsBitField = true, BitOffset = 16, Offset = 0, }); structure.Add(new CppField("bitfield2") { TypeName = "int", IsBitField = true, BitOffset = 16, Offset = 0 }); structure.Add(new CppField("pointer") { TypeName = "int", Pointer = "*", Offset = 1 }); structure.Add(new CppField("field") { TypeName = "int", Offset = 2, }); var include = new CppInclude("test"); include.Add(structure); var module = new CppModule("SharpGenTestModule"); module.Add(include); using (LoggerMessageCountEnvironment(1, LogLevel.Error)) using (LoggerCodeRequiredEnvironment(LoggingCodes.NonPortableAlignment)) { MapModel(module, config); } }
private static extern bool getStructData(ref CppStruct info);
public void MultipleBitfieldOffsetsGeneratedCorrectly() { var config = new ConfigFile { Id = nameof(MultipleBitfieldOffsetsGeneratedCorrectly), Namespace = nameof(MultipleBitfieldOffsetsGeneratedCorrectly), Includes = { new IncludeRule { File = "test.h", Attach = true, Namespace = nameof(MultipleBitfieldOffsetsGeneratedCorrectly) } }, Bindings = { new BindRule("int", "System.Int32") } }; var structure = new CppStruct("Test"); structure.Add(new CppField("bitfield1") { TypeName = "int", IsBitField = true, BitOffset = 16, Offset = 0, }); structure.Add(new CppField("field") { TypeName = "int", Offset = 1, }); structure.Add(new CppField("bitfield2") { TypeName = "int", IsBitField = true, BitOffset = 16, Offset = 2 }); 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(); var bitField1 = csStruct.Fields.First(field => field.Name == "Bitfield1"); Assert.Equal(0, bitField1.BitOffset); Assert.Equal(0u, bitField1.Offset); Assert.Equal((1 << 16) - 1, bitField1.BitMask); Assert.True(bitField1.IsBitField); var csField = csStruct.Fields.First(field => field.Name == "Field"); Assert.Equal(4u, csField.Offset); Assert.False(csField.IsBitField); var bitField2 = csStruct.Fields.First(field => field.Name == "Bitfield2"); Assert.Equal(0, bitField2.BitOffset); Assert.Equal(8u, bitField2.Offset); Assert.Equal((1 << 16) - 1, bitField2.BitMask); Assert.True(bitField2.IsBitField); }
public void NonPortableStructAlignmentRaisesError() { var config = new Config.ConfigFile { Id = nameof(NonPortableStructAlignmentRaisesError), Namespace = nameof(NonPortableStructAlignmentRaisesError), Includes = { new Config.IncludeRule { File = "test.h", Attach = true, Namespace = nameof(NonPortableStructAlignmentRaisesError) } }, Bindings = { new Config.BindRule("int", "System.Int32") } }; var structure = new CppStruct { Name = "Test" }; structure.Add(new CppField { Name = "bitfield1", TypeName = "int", IsBitField = true, BitOffset = 16, Offset = 0, }); structure.Add(new CppField { Name = "bitfield2", TypeName = "int", IsBitField = true, BitOffset = 16, Offset = 0 }); structure.Add(new CppField { Name = "pointer", TypeName = "int", Pointer = "*", Offset = 1 }); structure.Add(new CppField { Name = "field", TypeName = "int", Offset = 2, }); var include = new CppInclude { Name = "test" }; include.Add(structure); var module = new CppModule(); module.Add(include); var(solution, _) = MapModel(module, config); AssertLoggingCodeLogged(LoggingCodes.NonPortableAlignment); }
public CsStruct(CppStruct cppStruct) { IsIn = true; IsOut = false; CppElement = cppStruct; }