Inheritance: CppAst.CodeGen.CSharp.CSharpTypeWithMembers
Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }