public static CSharpPrimitiveType GetCSharpPrimitive(CppPrimitiveType cppType) { switch (cppType.Kind) { case CppPrimitiveKind.Void: return(CSharpPrimitiveType.Void()); case CppPrimitiveKind.Bool: return(CSharpPrimitiveType.Bool()); case CppPrimitiveKind.WChar: return(CSharpPrimitiveType.Char()); case CppPrimitiveKind.Char: return(CSharpPrimitiveType.SByte()); case CppPrimitiveKind.Short: return(CSharpPrimitiveType.Short()); case CppPrimitiveKind.Int: return(CSharpPrimitiveType.Int()); case CppPrimitiveKind.LongLong: return(CSharpPrimitiveType.Long()); case CppPrimitiveKind.UnsignedChar: return(CSharpPrimitiveType.Byte()); case CppPrimitiveKind.UnsignedShort: return(CSharpPrimitiveType.UShort()); case CppPrimitiveKind.UnsignedInt: return(CSharpPrimitiveType.UInt()); case CppPrimitiveKind.UnsignedLongLong: return(CSharpPrimitiveType.ULong()); case CppPrimitiveKind.Float: return(CSharpPrimitiveType.Float()); case CppPrimitiveKind.Double: return(CSharpPrimitiveType.Double()); case CppPrimitiveKind.LongDouble: return(CSharpPrimitiveType.Double()); default: throw new ArgumentOutOfRangeException($"The kind {cppType.Kind} is not supported"); } }
public static CSharpElement ConvertField(CSharpConverter converter, CppField cppField, CSharpElement context) { // Early exit if this is a global variable (we don't handle dllexport) bool isConst = cppField.Type is CppQualifiedType qualifiedType && qualifiedType.Qualifier == CppTypeQualifier.Const; var isGlobalVariable = (!(cppField.Parent is CppClass) && !isConst) || cppField.StorageQualifier == CppStorageQualifier.Static; if (isGlobalVariable) { return(null); } var isParentClass = cppField.Parent is CppClass; var csContainer = converter.GetCSharpContainer(cppField, context); var isUnion = ((cppField.Parent as CppClass)?.ClassKind ?? CppClassKind.Struct) == CppClassKind.Union; var csFieldName = converter.GetCSharpName(cppField, (CSharpElement)csContainer); if (cppField.IsBitField) { CSharpBitField csBitFieldStorage = null; for (var index = csContainer.Members.Count - 1; index >= 0; index--) { var member = csContainer.Members[index]; if (member is CSharpField csPreviousField) { csBitFieldStorage = csPreviousField as CSharpBitField; break; } } if (csBitFieldStorage == null || (csBitFieldStorage.CurrentBitWidth + cppField.BitFieldWidth) > csBitFieldStorage.MaxBitWidth) { var canonicalType = (CppPrimitiveType)cppField.Type.GetCanonicalType(); csBitFieldStorage = new CSharpBitField(BitFieldName + csContainer.Members.Count) { Visibility = CSharpVisibility.Private, }; switch (canonicalType.Kind) { case CppPrimitiveKind.Bool: csBitFieldStorage.FieldType = CSharpPrimitiveType.Byte(); csBitFieldStorage.MaxBitWidth = 8; break; case CppPrimitiveKind.WChar: csBitFieldStorage.FieldType = CSharpPrimitiveType.UShort(); csBitFieldStorage.MaxBitWidth = 16; break; case CppPrimitiveKind.Char: csBitFieldStorage.FieldType = CSharpPrimitiveType.Byte(); csBitFieldStorage.MaxBitWidth = 8; break; case CppPrimitiveKind.Short: csBitFieldStorage.FieldType = CSharpPrimitiveType.Short(); csBitFieldStorage.MaxBitWidth = 16; break; case CppPrimitiveKind.Int: csBitFieldStorage.FieldType = CSharpPrimitiveType.Int(); csBitFieldStorage.MaxBitWidth = 32; break; case CppPrimitiveKind.LongLong: csBitFieldStorage.FieldType = CSharpPrimitiveType.Long(); csBitFieldStorage.MaxBitWidth = 64; break; case CppPrimitiveKind.UnsignedChar: csBitFieldStorage.FieldType = CSharpPrimitiveType.Byte(); csBitFieldStorage.MaxBitWidth = 8; break; case CppPrimitiveKind.UnsignedShort: csBitFieldStorage.FieldType = CSharpPrimitiveType.UShort(); csBitFieldStorage.MaxBitWidth = 16; break; case CppPrimitiveKind.UnsignedInt: csBitFieldStorage.FieldType = CSharpPrimitiveType.UInt(); csBitFieldStorage.MaxBitWidth = 32; break; case CppPrimitiveKind.UnsignedLongLong: csBitFieldStorage.FieldType = CSharpPrimitiveType.ULong(); csBitFieldStorage.MaxBitWidth = 64; break; default: csBitFieldStorage.FieldType = new CSharpFreeType("unsupported_bitfield_type_" + canonicalType); csBitFieldStorage.MaxBitWidth = 128; break; } csContainer.Members.Add(csBitFieldStorage); } int currentBitOffset = csBitFieldStorage.CurrentBitWidth; csBitFieldStorage.CurrentBitWidth += cppField.BitFieldWidth; var csProperty = new CSharpProperty(csFieldName) { CppElement = cppField, LinkedField = csBitFieldStorage, }; converter.ApplyDefaultVisibility(csProperty, csContainer); csProperty.Comment = converter.GetCSharpComment(cppField, csProperty); var bitmask = (1L << cppField.BitFieldWidth) - 1; var bitmaskStr = $"0b{Convert.ToString(bitmask, 2)}"; var notBitMaskStr = Convert.ToString(~(bitmask << currentBitOffset), 2); if (notBitMaskStr.Length > csBitFieldStorage.MaxBitWidth) { notBitMaskStr = notBitMaskStr.Substring(notBitMaskStr.Length - csBitFieldStorage.MaxBitWidth); } csProperty.ReturnType = converter.GetCSharpType(cppField.Type, csProperty); csProperty.GetBody = (writer, element) => { writer.Write("return unchecked(("); csProperty.ReturnType.DumpReferenceTo(writer); writer.Write(")"); writer.Write($"(({csBitFieldStorage.Name} >> {currentBitOffset}) & {bitmaskStr})"); writer.Write(");"); writer.WriteLine(); }; csProperty.SetBody = (writer, element) => { writer.Write($"{csBitFieldStorage.Name} = ({csBitFieldStorage.Name} & unchecked(("); csBitFieldStorage.FieldType.DumpReferenceTo(writer); writer.Write($")0b{notBitMaskStr})) | (((("); csBitFieldStorage.FieldType.DumpReferenceTo(writer); writer.Write(")value) & (unchecked(("); csBitFieldStorage.FieldType.DumpReferenceTo(writer); writer.Write($"){bitmaskStr})) << {currentBitOffset}));"); writer.WriteLine(); }; csContainer.Members.Add(csProperty); return(csProperty); } var parentName = cppField.Parent is CppClass cppClass ? cppClass.Name : string.Empty; var csField = new CSharpField(csFieldName) { CppElement = cppField }; converter.ApplyDefaultVisibility(csField, csContainer); if (isConst) { if (isParentClass) { csField.Modifiers |= CSharpModifiers.ReadOnly; } else { csField.Modifiers |= CSharpModifiers.Const; } } csContainer.Members.Add(csField); csField.Comment = converter.GetCSharpComment(cppField, csField); if (isUnion) { csField.Attributes.Add(new CSharpFreeAttribute("FieldOffset(0)")); converter.AddUsing(csContainer, "System.Runtime.InteropServices"); } csField.FieldType = converter.GetCSharpType(cppField.Type, csField); if (cppField.InitExpression != null) { if (cppField.InitExpression.Kind == CppExpressionKind.Unexposed) { csField.InitValue = cppField.InitValue?.Value?.ToString(); } else { csField.InitValue = converter.ConvertExpression(cppField.InitExpression); } } return(csField); }