private CSharpElement ConvertTypedef(CSharpConverter converter, CppTypedef cppTypedef, CSharpElement context) { var elementType = cppTypedef.ElementType; if (DefaultFunctionTypeConverter.IsFunctionType(elementType, out var cppFunctionType)) { return(DefaultFunctionTypeConverter.ConvertNamedFunctionType(converter, cppFunctionType, context, cppTypedef)); } var isFromSystemIncludes = converter.IsFromSystemIncludes(cppTypedef); var csElementType = converter.GetCSharpType(elementType, context, true); var noWrap = converter.Options.TypedefCodeGenKind == CppTypedefCodeGenKind.NoWrap && !converter.Options.TypedefWrapWhiteList.Contains(cppTypedef.Name); // If: // - the typedef is from system includes and the underlying type is not a pointer // - or the typedef mode is "no-wrap" and is not in the whitelist // then we bypass entirely the typedef and return immediately the element type bool is_size_t = isFromSystemIncludes && cppTypedef.Name == "size_t"; if (noWrap || (isFromSystemIncludes && elementType.TypeKind != CppTypeKind.Pointer && !is_size_t)) { return(csElementType); } // Otherwise we generate a small wrapper struct var csStructName = converter.GetCSharpName(cppTypedef, context); var csStruct = new CSharpStruct(csStructName) { CppElement = cppTypedef, }; var container = converter.GetCSharpContainer(cppTypedef, context); converter.ApplyDefaultVisibility(csStruct, container); container.Members.Add(csStruct); csStruct.Comment = converter.GetCSharpComment(cppTypedef, csStruct); // Requires System.Runtime.InteropServices csStruct.Attributes.Add(new CSharpStructLayoutAttribute(LayoutKind.Sequential) { CharSet = converter.Options.DefaultCharSet }); // Required by StructLayout converter.AddUsing(container, "System.Runtime.InteropServices"); var name = csStruct.Name; csStruct.Modifiers |= CSharpModifiers.ReadOnly; csStruct.BaseTypes.Add(new CSharpFreeType($"IEquatable<{name}>")); // Dump the type name and attached attributes for the element type var attachedAttributes = string.Empty; var csElementTypeName = is_size_t ? "IntPtr" : converter.ConvertTypeReferenceToString(csElementType, out attachedAttributes); csStruct.Members.Add(new CSharpLineElement($"public {name}({csElementTypeName} value) => this.Value = value;")); csStruct.Members.Add(new CSharpLineElement($"{attachedAttributes}public readonly {csElementTypeName} Value;")); csStruct.Members.Add(new CSharpLineElement($"public bool Equals({name} other) => Value.Equals(other.Value);")); csStruct.Members.Add(new CSharpLineElement($"public override bool Equals(object obj) => obj is {name} other && Equals(other);")); csStruct.Members.Add(new CSharpLineElement($"public override int GetHashCode() => Value.GetHashCode();")); csStruct.Members.Add(new CSharpLineElement($"public override string ToString() => Value.ToString();")); csStruct.Members.Add(new CSharpLineElement($"public static implicit operator {csElementTypeName}({name} from) => from.Value;")); csStruct.Members.Add(new CSharpLineElement($"public static implicit operator {name}({csElementTypeName} from) => new {name}(from);")); csStruct.Members.Add(new CSharpLineElement($"public static bool operator ==({name} left, {name} right) => left.Equals(right);")); csStruct.Members.Add(new CSharpLineElement($"public static bool operator !=({name} left, {name} right) => !left.Equals(right);")); return(csStruct); }
public static CSharpElement ConvertClass(CSharpConverter converter, CppClass cppClass, CSharpElement context) { // This converter supports only plain struct or union if (cppClass.ClassKind == CppClassKind.Class && cppClass.Functions.Any(x => (x.Flags & CppFunctionFlags.Virtual) != 0)) { return(null); } // Register the struct as soon as possible var csStructName = converter.GetCSharpName(cppClass, context); var csStruct = new CSharpStruct(csStructName) { CppElement = cppClass, }; var container = converter.GetCSharpContainer(cppClass, context); converter.ApplyDefaultVisibility(csStruct, container); if (container is CSharpInterface) { container = container.Parent; } container.Members.Add(csStruct); csStruct.Comment = converter.GetCSharpComment(cppClass, csStruct); bool isUnion = cppClass.ClassKind == CppClassKind.Union; // Requires System.Runtime.InteropServices csStruct.Attributes.Add(isUnion ? new CSharpStructLayoutAttribute(LayoutKind.Explicit) { CharSet = converter.Options.DefaultCharSet } : new CSharpStructLayoutAttribute(LayoutKind.Sequential) { CharSet = converter.Options.DefaultCharSet } ); // Required by StructLayout converter.AddUsing(container, "System.Runtime.InteropServices"); if (cppClass.BaseTypes.Count == 1) { var csBaseType = converter.GetCSharpType(cppClass.BaseTypes[0].Type, context, false); csStruct.Members.Add(new CSharpField("@base") { FieldType = csBaseType, Visibility = CSharpVisibility.Public }); } // For opaque type we use a standard representation if (!cppClass.IsDefinition && cppClass.Fields.Count == 0) { csStruct.Modifiers |= CSharpModifiers.ReadOnly; csStruct.BaseTypes.Add(new CSharpFreeType($"IEquatable<{csStruct.Name}>")); csStruct.Members.Add(new CSharpLineElement("private readonly IntPtr _handle;")); csStruct.Members.Add(new CSharpLineElement($"public {csStruct.Name}(IntPtr handle) => _handle = handle;")); csStruct.Members.Add(new CSharpLineElement("public IntPtr Handle => _handle;")); csStruct.Members.Add(new CSharpLineElement($"public bool Equals({csStruct.Name} other) => _handle.Equals(other._handle);")); csStruct.Members.Add(new CSharpLineElement($"public override bool Equals(object obj) => obj is {csStruct.Name} other && Equals(other);")); csStruct.Members.Add(new CSharpLineElement($"public override int GetHashCode() => _handle.GetHashCode();")); csStruct.Members.Add(new CSharpLineElement($"public override string ToString() => \"0x\" + (IntPtr.Size == 8 ? _handle.ToString(\"X16\") : _handle.ToString(\"X8\"));")); csStruct.Members.Add(new CSharpLineElement($"public static bool operator ==({csStruct.Name} left, {csStruct.Name} right) => left.Equals(right);")); csStruct.Members.Add(new CSharpLineElement($"public static bool operator !=({csStruct.Name} left, {csStruct.Name} right) => !left.Equals(right);")); } // If we have any anonymous structs/unions for a field type // try to compute a name for them before processing them foreach (var cppField in cppClass.Fields) { var fieldType = cppField.Type; if (fieldType is CppClass cppFieldTypeClass && cppFieldTypeClass.IsAnonymous && string.IsNullOrEmpty(cppFieldTypeClass.Name)) { var parentName = string.Empty; if (cppFieldTypeClass.Parent is CppClass cppParentClass) { parentName = cppParentClass.Name; } if (cppFieldTypeClass.ClassKind == CppClassKind.Union) { parentName = parentName == string.Empty ? "union" : parentName + "_union"; } cppFieldTypeClass.Name = $"{parentName}_{cppField.Name}"; } } return(csStruct); }