/// <summary> /// Prepares the specified C++ element to a C# element. /// </summary> /// <param name="cppElement">The C++ element.</param> /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns> public override CsBase Prepare(CppElement cppElement) { var cppInterface = (CppInterface)cppElement; // IsFullyMapped to false => The structure is being mapped var cSharpInterface = new CsInterface(cppInterface) { IsFullyMapped = false }; CsNamespace nameSpace = Manager.ResolveNamespace(cppInterface); cSharpInterface.Name = NamingRules.Rename(cppInterface); nameSpace.Add(cSharpInterface); Manager.BindType(cppInterface.Name, cSharpInterface); return(cSharpInterface); }
/// <summary> /// Prepares C++ struct for mapping. This method is creating the associated C# struct. /// </summary> /// <param name="cppStruct">The c++ struct.</param> /// <returns></returns> public override CsStruct Prepare(CppStruct cppStruct) { // Create a new C# struct var nameSpace = namespaceRegistry.ResolveNamespace(cppStruct); var csStruct = new CsStruct(cppStruct) { Name = NamingRules.Rename(cppStruct), // IsFullyMapped to false => The structure is being mapped IsFullyMapped = false }; // Add the C# struct to its namespace nameSpace.Add(csStruct); // Map the C++ name to the C# struct typeRegistry.BindType(cppStruct.Name, csStruct); return(csStruct); }
/// <summary> /// Processes the specified method. /// </summary> /// <param name="method">The method.</param> private void ProcessMethod(CsCallable method) { var cppMethod = (CppCallable)method.CppElement; method.Name = NamingRules.Rename(cppMethod); // For methods, the tag "type" is only used for return type // So we are overriding the return type here var methodRule = cppMethod.GetMappingRule(); if (methodRule.MappingType != null) { cppMethod.ReturnValue.Rule = new MappingRule { MappingType = methodRule.MappingType } } ; // Get the inferred return type method.ReturnValue = factory.Create(cppMethod.ReturnValue); if (method.ReturnValue.PublicType is CsInterface iface && iface.IsCallback) { method.ReturnValue.PublicType = iface.GetNativeImplementationOrThis(); } // Hide return type only if it is a HRESULT and AlwaysReturnHResult is false if (method.CheckReturnType && method.ReturnValue.PublicType != null && method.ReturnValue.PublicType.QualifiedName == globalNamespace.GetTypeName(WellKnownName.Result)) { method.HideReturnType = !method.AlwaysReturnHResult; } // Iterates on parameters to convert them to C# parameters foreach (var cppParameter in cppMethod.Parameters) { var paramMethod = factory.Create(cppParameter); paramMethod.Name = NamingRules.Rename(cppParameter); method.Add(paramMethod); } }
/// <summary> /// Prepares C++ struct for mapping. This method is creating the associated C# struct. /// </summary> /// <param name="cppElement">The c++ struct.</param> /// <returns></returns> public override CsBase Prepare(CppElement cppElement) { var cppStruct = (CppStruct)cppElement; // Create a new C# struct var nameSpace = Manager.ResolveNamespace(cppStruct); var csStruct = new CsStruct(cppStruct) { Name = NamingRules.Rename(cppStruct), // IsFullyMapped to false => The structure is being mapped IsFullyMapped = false }; // Add the C# struct to its namespace nameSpace.Add(csStruct); // Map the C++ name to the C# struct Manager.BindType(cppStruct.Name, csStruct); return(csStruct); }
/// <summary> /// Prepares the specified C++ element to a C# element. /// </summary> /// <param name="cppEnum">The C++ element.</param> /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns> public override CsEnum Prepare(CppEnum cppEnum) { // Create C# enum var newEnum = new CsEnum { Name = NamingRules.Rename(cppEnum), CppElement = cppEnum, UnderlyingType = typeRegistry.ImportType(typeof(int)) }; // Get the namespace for this particular include and enum var nameSpace = namespaceRegistry.ResolveNamespace(cppEnum); nameSpace.Add(newEnum); // Bind C++ enum to C# enum typeRegistry.BindType(cppEnum.Name, newEnum); return(newEnum); }
/// <summary> /// Prepares the specified C++ element to a C# element. /// </summary> /// <param name="cppElement">The C++ element.</param> /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns> public override CsBase Prepare(CppElement cppElement) { var cppEnum = (CppEnum)cppElement; // Create C# enum var newEnum = new CsEnum { Name = NamingRules.Rename(cppEnum), CppElement = cppEnum }; // Get the namespace for this particular include and enum var nameSpace = Manager.ResolveNamespace(cppEnum); nameSpace.Add(newEnum); // Bind C++ enum to C# enum Manager.BindType(cppEnum.Name, newEnum); return(newEnum); }
/// <summary> /// Prepares the specified C++ element to a C# element. /// </summary> /// <param name="cppInterface">The C++ element.</param> /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns> public override CsInterface Prepare(CppInterface cppInterface) { // IsFullyMapped to false => The structure is being mapped var cSharpInterface = new CsInterface(cppInterface) { IsFullyMapped = false }; var nameSpace = namespaceRegistry.ResolveNamespace(cppInterface); cSharpInterface.Name = NamingRules.Rename(cppInterface); nameSpace.Add(cSharpInterface); typeRegistry.BindType(cppInterface.Name, cSharpInterface); foreach (var cppMethod in cppInterface.Methods) { cSharpInterface.Add(MethodPreparer.Prepare(cppMethod)); } return(cSharpInterface); }
/// <summary> /// Processes the specified method. /// </summary> /// <param name="method">The method.</param> private void Process(CsMethod method) { var cppMethod = (CppMethod)method.CppElement; method.Name = NamingRules.Rename(cppMethod); method.Offset = cppMethod.Offset; // For methods, the tag "type" is only used for return type // So we are overriding the return type here var tag = cppMethod.GetTagOrDefault <MappingRule>(); if (tag.MappingType != null) { cppMethod.ReturnType.Tag = new MappingRule { MappingType = tag.MappingType } } ; // Apply any offset to the method's vtable method.Offset += tag.LayoutOffsetTranslate; // Get the inferred return type method.ReturnType = Manager.GetCsType <CsMarshalBase>(cppMethod.ReturnType); // Hide return type only if it is a HRESULT and AlwaysReturnHResult is false if (method.CheckReturnType && method.ReturnType.PublicType != null && method.ReturnType.PublicType.QualifiedName == Manager.GlobalNamespace.GetTypeName("Result")) { method.HideReturnType = !method.AlwaysReturnHResult; } // Iterates on parameters to convert them to C# parameters foreach (var cppParameter in cppMethod.Parameters) { var cppAttribute = cppParameter.Attribute; var paramTag = cppParameter.GetTagOrDefault <MappingRule>(); bool hasArray = cppParameter.IsArray || ((cppAttribute & ParamAttribute.Buffer) != 0); bool hasParams = (cppAttribute & ParamAttribute.Params) == ParamAttribute.Params; bool isOptional = (cppAttribute & ParamAttribute.Optional) != 0; var paramMethod = Manager.GetCsType <CsParameter>(cppParameter); paramMethod.Name = NamingRules.Rename(cppParameter); bool hasPointer = paramMethod.HasPointer; var publicType = paramMethod.PublicType; var marshalType = paramMethod.MarshalType; CsParameterAttribute parameterAttribute = CsParameterAttribute.In; if (hasArray) { hasPointer = true; } // -------------------------------------------------------------------------------- // Pointer - Handle special cases // -------------------------------------------------------------------------------- if (hasPointer) { marshalType = Manager.ImportType(typeof(IntPtr)); // -------------------------------------------------------------------------------- // Handling Parameter Interface // -------------------------------------------------------------------------------- if (publicType is CsInterface) { // Force Interface** to be ParamAttribute.Out when None if (cppAttribute == ParamAttribute.In) { if (cppParameter.Pointer == "**") { cppAttribute = ParamAttribute.Out; } } if ((cppAttribute & ParamAttribute.In) != 0 || (cppAttribute & ParamAttribute.InOut) != 0) { parameterAttribute = CsParameterAttribute.In; // Force all array of interface to support null if (hasArray) { isOptional = true; } // If Interface is a callback, use IntPtr as a public marshalling type CsInterface publicCsInterface = (CsInterface)publicType; if (publicCsInterface.IsCallback) { publicType = Manager.ImportType(typeof(IntPtr)); // By default, set the Visibility to internal for methods using callbacks // as we need to provide user method. Don't do this on functions as they // are already hidden by the container if (!(method is CsFunction)) { method.Visibility = Visibility.Internal; method.Name = method.Name + "_"; } } } //else if ((cppParameter.Attribute & ParamAttribute.InOut) != 0) // parameterAttribute = method.ParameterAttribute.Ref; else if ((cppAttribute & ParamAttribute.Out) != 0) { parameterAttribute = CsParameterAttribute.Out; } } else { // If a pointer to array of bool are handle as array of int if (paramMethod.IsBoolToInt && (cppAttribute & ParamAttribute.Buffer) != 0) { publicType = Manager.ImportType(typeof(int)); } // -------------------------------------------------------------------------------- // Handling Parameter Interface // -------------------------------------------------------------------------------- if ((cppAttribute & ParamAttribute.In) != 0) { parameterAttribute = publicType.Type == typeof(IntPtr) || publicType.Name == Manager.GlobalNamespace.GetTypeName("FunctionCallback") || publicType.Type == typeof(string) ? CsParameterAttribute.In : CsParameterAttribute.RefIn; } else if ((cppAttribute & ParamAttribute.InOut) != 0) { if ((cppAttribute & ParamAttribute.Optional) != 0) { publicType = Manager.ImportType(typeof(IntPtr)); parameterAttribute = CsParameterAttribute.In; } else { parameterAttribute = CsParameterAttribute.Ref; } } else if ((cppAttribute & ParamAttribute.Out) != 0) { parameterAttribute = CsParameterAttribute.Out; } // Handle void* with Buffer attribute if (cppParameter.TypeName == "void" && (cppAttribute & ParamAttribute.Buffer) != 0) { hasArray = false; parameterAttribute = CsParameterAttribute.In; } else if (publicType.Type == typeof(string) && (cppAttribute & ParamAttribute.Out) != 0) { publicType = Manager.ImportType(typeof(IntPtr)); parameterAttribute = CsParameterAttribute.In; hasArray = false; } else if (publicType is CsStruct && (parameterAttribute == CsParameterAttribute.Out || hasArray || parameterAttribute == CsParameterAttribute.RefIn || parameterAttribute == CsParameterAttribute.Ref)) { // Set IsOut on structure to generate proper marshalling (publicType as CsStruct).IsOut = true; } } } paramMethod.HasPointer = hasPointer; paramMethod.Attribute = parameterAttribute; paramMethod.IsArray = hasArray; paramMethod.HasParams = hasParams; paramMethod.HasPointer = hasPointer; paramMethod.PublicType = publicType ?? throw new ArgumentException("Public type cannot be null"); paramMethod.MarshalType = marshalType; paramMethod.IsOptional = isOptional; // Force IsString to be only string (due to Buffer attribute) if (paramMethod.IsString) { paramMethod.IsArray = false; } method.Add(paramMethod); } } }
/// <summary> /// Maps the C++ struct to C# struct. /// </summary> /// <param name="csStruct">The c sharp struct.</param> private void Process(CsStruct csStruct) { // TODO: this mapping must be robust. Current calculation for field offset is not always accurate for union. // TODO: need to handle align/packing correctly. // If a struct was already mapped, then return immediately // The method MapStruct can be called recursively if (csStruct.IsFullyMapped) { return; } // Set IsFullyMappy in order to avoid recursive mapping csStruct.IsFullyMapped = true; // Get the associated CppStruct and CSharpTag var cppStruct = (CppStruct)csStruct.CppElement; bool hasMarshalType = csStruct.HasMarshalType; // If this structure need to me moved to another container, move it now foreach (var keyValuePair in _mapMoveStructToInner) { if (keyValuePair.Key.Match(csStruct.CppElementName).Success) { string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value); var destSharpStruct = (CsStruct)Manager.FindBindType(cppName); // Remove the struct from his container csStruct.Parent.Remove(csStruct); // Add this struct to the new container struct destSharpStruct.Add(csStruct); } } // Current offset of a field int currentFieldAbsoluteOffset = 0; // Last field offset int previousFieldOffsetIndex = -1; // Size of the last field int previousFieldSize = 0; // int maxSizeOfField = 0; bool isInUnion = false; int cumulatedBitOffset = 0; var inheritedStructs = new Stack <CppStruct>(); var currentStruct = cppStruct; while (currentStruct != null && currentStruct.ParentName != currentStruct.Name) { inheritedStructs.Push(currentStruct); currentStruct = Manager.FindBindType(currentStruct.ParentName)?.CppElement as CppStruct; } while (inheritedStructs.Count > 0) { currentStruct = inheritedStructs.Pop(); int fieldCount = currentStruct.IsEmpty ? 0 : currentStruct.Items.Count; // ------------------------------------------------------------------------------- // Iterate on all fields and perform mapping // ------------------------------------------------------------------------------- for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) { var cppField = (CppField)currentStruct.Items[fieldIndex]; Logger.RunInContext(cppField.ToString(), () => { var fieldStruct = Manager.GetCsType <CsField>(cppField, true); csStruct.Add(fieldStruct); // Get name fieldStruct.Name = NamingRules.Rename(cppField); // BoolToInt doesn't generate native Marshaling although they have a different marshaller if (!fieldStruct.IsBoolToInt && fieldStruct.HasMarshalType) { hasMarshalType = true; } // If last field has same offset, then it's a union // CurrentOffset is not moved if (isInUnion && previousFieldOffsetIndex != cppField.Offset) { previousFieldSize = maxSizeOfField; maxSizeOfField = 0; isInUnion = false; } currentFieldAbsoluteOffset += previousFieldSize; var fieldAlignment = (fieldStruct.MarshalType ?? fieldStruct.PublicType).CalculateAlignment(); // If field alignment is < 0, then we have a pointer somewhere so we can't align if (fieldAlignment > 0) { // otherwise, align the field on the alignment requirement of the field int delta = (currentFieldAbsoluteOffset % fieldAlignment); if (delta != 0) { currentFieldAbsoluteOffset += fieldAlignment - delta; } } // Get correct offset (for handling union) fieldStruct.Offset = currentFieldAbsoluteOffset; fieldStruct.IsBitField = cppField.IsBitField; // Handle bit fields : calculate BitOffset and BitMask for this field if (previousFieldOffsetIndex != cppField.Offset) { cumulatedBitOffset = 0; } if (cppField.IsBitField) { int lastCumulatedBitOffset = cumulatedBitOffset; cumulatedBitOffset += cppField.BitOffset; fieldStruct.BitMask = ((1 << cppField.BitOffset) - 1); // &~((1 << (lastCumulatedBitOffset + 1)) - 1); fieldStruct.BitOffset = lastCumulatedBitOffset; } var nextFieldIndex = fieldIndex + 1; if ((previousFieldOffsetIndex == cppField.Offset) || (nextFieldIndex < fieldCount && ((CppField)currentStruct.Items[nextFieldIndex]).Offset == cppField.Offset)) { if (previousFieldOffsetIndex != cppField.Offset) { maxSizeOfField = 0; } maxSizeOfField = fieldStruct.SizeOf > maxSizeOfField ? fieldStruct.SizeOf : maxSizeOfField; isInUnion = true; csStruct.ExplicitLayout = true; previousFieldSize = 0; } else { previousFieldSize = fieldStruct.SizeOf; } previousFieldOffsetIndex = cppField.Offset; }); } } // In case of explicit layout, check that we can safely generate it on both x86 and x64 (in case of an union // using pointers, we can't) if (csStruct.ExplicitLayout) { var fieldList = csStruct.Fields.ToList(); for (int i = 0; i < fieldList.Count; i++) { var field = fieldList[i]; var fieldAlignment = (field.MarshalType ?? field.PublicType).CalculateAlignment(); if (fieldAlignment < 0) { // If pointer field is not the last one, than we can't handle it if ((i + 1) < fieldList.Count) { Logger.Error( "The field [{0}] in structure [{1}] has pointer alignment within a structure that contains an union. An explicit layout cannot be handled on both x86/x64. This structure needs manual layout (remove fields from definition) and write them manually in xml mapping files", field.CppElementName, csStruct.CppElementName); break; } } } } csStruct.SizeOf = currentFieldAbsoluteOffset + previousFieldSize; csStruct.HasMarshalType = hasMarshalType; }
/// <summary> /// Maps the C++ struct to C# struct. /// </summary> /// <param name="csStruct">The c sharp struct.</param> private void Process(CsStruct csStruct) { // TODO: this mapping must be robust. Current caculation for field offset is not always accurate for union. // TODO: need to handle align/packing correctly. // If a struct was already mapped, then return immediatly // The method MapStruct can be called recursivelly if (csStruct.IsFullyMapped) { return; } // Set IsFullyMappy in order to avoid recursive mapping csStruct.IsFullyMapped = true; // Get the associated CppStruct and CSharpTag var cppStruct = (CppStruct)csStruct.CppElement; bool hasMarshalType = csStruct.HasMarshalType; // If this structure need to me moved to anoter container, move it now foreach (var keyValuePair in _mapMoveStructToInner) { if (keyValuePair.Key.Match(csStruct.CppElementName).Success) { string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value); var destSharpStruct = (CsStruct)Manager.FindBindType(cppName); // Remove the struct from his container csStruct.Parent.Remove(csStruct); // Add this struct to the new container struct destSharpStruct.Add(csStruct); } } // Current offset of a field int currentOffset = 0; int fieldCount = cppStruct.IsEmpty ? 0 : cppStruct.Items.Count; // Offset stored for each field int[] offsetOfFields = new int[fieldCount]; // Last field offset int lastCppFieldOffset = -1; // Size of the last field int lastFieldSize = 0; // int maxSizeOfField = 0; bool isInUnion = false; int cumulatedBitOffset = 0; // ------------------------------------------------------------------------------- // Iterate on all fields and perform mapping // ------------------------------------------------------------------------------- for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) { var cppField = (CppField)cppStruct.Items[fieldIndex]; Logger.RunInContext(cppField.ToString(), () => { var fieldStruct = Manager.GetCsType <CsField>(cppField, true); // Get name fieldStruct.Name = NamingRules.Rename(cppField); // BoolToInt doesn't generate native Marshaling although they have a different marshaller if (!fieldStruct.IsBoolToInt && fieldStruct.HasMarshalType) { hasMarshalType = true; } // If last field has same offset, then it's a union // CurrentOffset is not moved if (isInUnion && lastCppFieldOffset != cppField.Offset) { lastFieldSize = maxSizeOfField; maxSizeOfField = 0; isInUnion = false; } currentOffset += lastFieldSize; offsetOfFields[cppField.Offset] = currentOffset; // Get correct offset (for handling union) fieldStruct.Offset = offsetOfFields[cppField.Offset]; fieldStruct.IsBitField = cppField.IsBitField; // Handle bit fields : calculate BitOffset and BitMask for this field if (lastCppFieldOffset != cppField.Offset) { cumulatedBitOffset = 0; } if (cppField.IsBitField) { int lastCumulatedBitOffset = cumulatedBitOffset; cumulatedBitOffset += cppField.BitOffset; fieldStruct.BitMask = ((1 << cppField.BitOffset) - 1); // &~((1 << (lastCumulatedBitOffset + 1)) - 1); //fieldStruct.BitMask2 = ((1 << cppField.BitOffset) - 1); // &~((1 << (lastCumulatedBitOffset + 1)) - 1); fieldStruct.BitOffset = lastCumulatedBitOffset; } csStruct.Add(fieldStruct); // TODO : handle packing rules here!!!!! // If last field has same offset, then it's a union // CurrentOffset is not moved if (lastCppFieldOffset == cppField.Offset || ((fieldIndex + 1) < fieldCount && (cppStruct.Items[fieldIndex + 1] as CppField).Offset == cppField.Offset)) { isInUnion = true; csStruct.ExplicitLayout = true; maxSizeOfField = fieldStruct.SizeOf > maxSizeOfField ? fieldStruct.SizeOf : maxSizeOfField; lastFieldSize = 0; } else { lastFieldSize = fieldStruct.SizeOf; } lastCppFieldOffset = cppField.Offset; }); } csStruct.SizeOf = currentOffset + lastFieldSize; csStruct.HasMarshalType = hasMarshalType; }
/// <summary> /// Maps the C++ struct to C# struct. /// </summary> /// <param name="csStruct">The c sharp struct.</param> public override void Process(CsStruct csStruct) { // TODO: this mapping must be robust. Current calculation for field offset is not always accurate for union. // TODO: need to handle align/packing correctly. // If a struct was already mapped, then return immediately // The method MapStruct can be called recursively if (csStruct.IsFullyMapped) { return; } // Set IsFullyMappy in order to avoid recursive mapping csStruct.IsFullyMapped = true; // Get the associated CppStruct and CSharpTag var cppStruct = (CppStruct)csStruct.CppElement; bool hasMarshalType = csStruct.HasMarshalType; // If this structure need to me moved to another container, move it now foreach (var keyValuePair in _mapMoveStructToInner) { if (keyValuePair.Key.Match(csStruct.CppElementName).Success) { string cppName = keyValuePair.Key.Replace(csStruct.CppElementName, keyValuePair.Value); var destSharpStruct = (CsStruct)typeRegistry.FindBoundType(cppName); // Remove the struct from his container csStruct.Parent.Remove(csStruct); // Add this struct to the new container struct destSharpStruct.Add(csStruct); } } // Current offset of a field int currentFieldAbsoluteOffset = 0; // Last field offset int previousFieldOffsetIndex = -1; // Size of the last field int previousFieldSize = 0; // int maxSizeOfField = 0; bool isNonSequential = false; int cumulatedBitOffset = 0; var inheritedStructs = new Stack <CppStruct>(); var currentStruct = cppStruct; while (currentStruct != null && currentStruct.Base != currentStruct.Name) { inheritedStructs.Push(currentStruct); currentStruct = typeRegistry.FindBoundType(currentStruct.Base)?.CppElement as CppStruct; } while (inheritedStructs.Count > 0) { currentStruct = inheritedStructs.Pop(); int fieldCount = currentStruct.IsEmpty ? 0 : currentStruct.Items.Count; // ------------------------------------------------------------------------------- // Iterate on all fields and perform mapping // ------------------------------------------------------------------------------- for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) { var cppField = (CppField)currentStruct.Items[fieldIndex]; Logger.RunInContext(cppField.ToString(), () => { var csField = factory.Create(cppField); csStruct.Add(csField); // Get name csField.Name = NamingRules.Rename(cppField); var fieldHasMarshalType = csField.PublicType != csField.MarshalType || (csField.PublicType is CsStruct fieldStruct && fieldStruct.HasMarshalType) || csField.IsArray; // BoolToInt doesn't generate native Marshaling although they have a different marshaller if (((!csField.IsBoolToInt || csField.IsArray) && fieldHasMarshalType) || csField.Relation != null) { hasMarshalType = true; } // If last field has same offset, then it's a union // CurrentOffset is not moved if (isNonSequential && previousFieldOffsetIndex != cppField.Offset) { previousFieldSize = maxSizeOfField; maxSizeOfField = 0; isNonSequential = false; } currentFieldAbsoluteOffset += previousFieldSize; var fieldAlignment = (csField.MarshalType ?? csField.PublicType).CalculateAlignment(); // If field alignment is < 0, then we have a pointer somewhere so we can't align if (fieldAlignment > 0) { // otherwise, align the field on the alignment requirement of the field int delta = (currentFieldAbsoluteOffset % fieldAlignment); if (delta != 0) { currentFieldAbsoluteOffset += fieldAlignment - delta; } } // Get correct offset (for handling union) csField.Offset = currentFieldAbsoluteOffset; // Handle bit fields : calculate BitOffset and BitMask for this field if (previousFieldOffsetIndex != cppField.Offset) { cumulatedBitOffset = 0; } if (cppField.IsBitField) { int lastCumulatedBitOffset = cumulatedBitOffset; cumulatedBitOffset += cppField.BitOffset; csField.BitMask = ((1 << cppField.BitOffset) - 1); csField.BitOffset = lastCumulatedBitOffset; } var nextFieldIndex = fieldIndex + 1; if ((previousFieldOffsetIndex == cppField.Offset) || (nextFieldIndex < fieldCount && ((CppField)currentStruct.Items[nextFieldIndex]).Offset == cppField.Offset)) { if (previousFieldOffsetIndex != cppField.Offset) { maxSizeOfField = 0; } maxSizeOfField = csField.Size > maxSizeOfField ? csField.Size : maxSizeOfField; isNonSequential = true; csStruct.ExplicitLayout = true; previousFieldSize = 0; } else { previousFieldSize = csField.Size; } previousFieldOffsetIndex = cppField.Offset; });
/// <summary> /// Maps a C++ Enum to a C# enum. /// </summary> /// <param name="newEnum">the C# enum.</param> private void Process(CsEnum newEnum) { var cppEnum = (CppEnum)newEnum.CppElement; // Get tag from C++ enum var tag = cppEnum.GetTagOrDefault <MappingRule>(); // Determine enum type. Default is int string typeName = cppEnum.GetTypeNameWithMapping(); switch (typeName) { case "byte": newEnum.Type = typeof(byte); newEnum.SizeOf = 1; break; case "short": newEnum.Type = typeof(short); newEnum.SizeOf = 1; break; case "int": newEnum.Type = typeof(int); newEnum.SizeOf = 4; break; default: Logger.Error("Invalid type [{0}] for enum [{1}]. Types supported are : int, byte, short", typeName, cppEnum); break; } // Find Root Name of this enum // All enum items should start with the same root name and the root name should be at least 4 chars string rootName = cppEnum.Name; string rootNameFound = null; bool isRootNameFound = false; for (int i = rootName.Length; i >= 4 && !isRootNameFound; i--) { rootNameFound = rootName.Substring(0, i); isRootNameFound = true; foreach (var cppEnumItem in cppEnum.EnumItems) { if (!cppEnumItem.Name.StartsWith(rootNameFound)) { isRootNameFound = false; break; } } } if (isRootNameFound) { rootName = rootNameFound; } // Create enum items for enum foreach (var cppEnumItem in cppEnum.EnumItems) { string enumName = NamingRules.Rename(cppEnumItem, rootName); string enumValue = cppEnumItem.Value; var csharpEnumItem = new CsEnumItem(enumName, enumValue) { CppElement = cppEnumItem }; newEnum.Add(csharpEnumItem); if (cppEnumItem.Name != "None") { Manager.BindType(cppEnumItem.Name, csharpEnumItem); } } bool tryToAddNone = tag.EnumHasNone.HasValue ? tag.EnumHasNone.Value : false; // If C++ enum name is ending with FLAG OR FLAGS // Then tag this enum as flags and add None if necessary if (cppEnum.Name.EndsWith("FLAG") || cppEnum.Name.EndsWith("FLAGS")) { newEnum.IsFlag = true; if (!tag.EnumHasNone.HasValue) { tryToAddNone = !newEnum.Items.Cast <CsEnumItem>().Any(item => item.Name == "None"); } } // Add None value if (tryToAddNone) { var csharpEnumItem = new CsEnumItem("None", "0"); csharpEnumItem.CppElement = new CppElement { Description = "None." }; newEnum.Add(csharpEnumItem); } }
/// <summary> /// Maps a C++ Enum to a C# enum. /// </summary> /// <param name="newEnum">the C# enum.</param> public override void Process(CsEnum newEnum) { var cppEnum = (CppEnum)newEnum.CppElement; // Determine enum type. Default is int var typeName = cppEnum.GetTypeNameWithMapping(); switch (typeName) { case "byte": newEnum.UnderlyingType = typeRegistry.ImportType(typeof(byte)); break; case "short": newEnum.UnderlyingType = typeRegistry.ImportType(typeof(short)); break; case "ushort": newEnum.UnderlyingType = typeRegistry.ImportType(typeof(ushort)); break; case "int": newEnum.UnderlyingType = typeRegistry.ImportType(typeof(int)); break; case "uint": newEnum.UnderlyingType = typeRegistry.ImportType(typeof(uint)); break; default: Logger.Error(LoggingCodes.InvalidUnderlyingType, "Invalid type [{0}] for enum [{1}]. Types supported are : int, byte, short", typeName, cppEnum); break; } // Find Root Name of this enum // All enum items should start with the same root name and the root name should be at least 4 chars string rootName = cppEnum.Name; string rootNameFound = null; bool isRootNameFound = false; for (int i = rootName.Length; i >= 4 && !isRootNameFound; i--) { rootNameFound = rootName.Substring(0, i); isRootNameFound = true; foreach (var cppEnumItem in cppEnum.EnumItems) { if (!cppEnumItem.Name.StartsWith(rootNameFound)) { isRootNameFound = false; break; } } } if (isRootNameFound) { rootName = rootNameFound; } // Create enum items for enum foreach (var cppEnumItem in cppEnum.EnumItems) { string enumName = NamingRules.Rename(cppEnumItem, rootName); string enumValue = cppEnumItem.Value; var csharpEnumItem = new CsEnumItem(enumName, enumValue) { CppElement = cppEnumItem }; newEnum.Add(csharpEnumItem); } var rule = cppEnum.GetMappingRule(); bool tryToAddNone = rule.EnumHasNone ?? false; // If C++ enum name is ending with FLAG OR FLAGS // Then tag this enum as flags and add None if necessary if (cppEnum.Name.EndsWith("FLAG") || cppEnum.Name.EndsWith("FLAGS")) { newEnum.IsFlag = true; if (!rule.EnumHasNone.HasValue) { tryToAddNone = !newEnum.EnumItems.Any(item => item.Name == "None"); } } // Add None value if (tryToAddNone) { var csharpEnumItem = new CsEnumItem("None", "0") { CppElementName = "None", Description = "None" }; newEnum.Add(csharpEnumItem); } }