Esempio n. 1
0
 void ICSharpContainer.ValidateMember(CSharpElement element)
 {
     if (!(element is CSharpGeneratedFile))
     {
         throw new ArgumentException("Only instance of CSharpGeneratedFile can be added to members of a CSharpCompilation");
     }
 }
Esempio n. 2
0
 public void ValidateMember(CSharpElement element)
 {
     if (element is CSharpCompilation || element is CSharpGeneratedFile || element is CSharpNamespace)
     {
         throw new ArgumentException($"Cannot add a {element.GetType().Name} to members of a {this.GetType().Name}");
     }
 }
        public static void DumpContextualAttributesTo(this CSharpElement element, CodeWriter writer, bool inline = false, CSharpAttributeScope?scopeOverride = null)
        {
            if (!(element is ICSharpContextualAttributesProvider provider))
            {
                return;
            }

            var mode = writer.Mode;

            if (mode == CodeWriterMode.Simple)
            {
                return;
            }

            if (inline)
            {
                bool isFirst = true;

                foreach (var attr in provider.GetContextualAttributes())
                {
                    if (isFirst)
                    {
                        writer.Write("[");
                        isFirst = false;
                    }
                    else
                    {
                        writer.Write("] [");
                    }

                    if (scopeOverride.HasValue)
                    {
                        attr.DumpTo(writer, scopeOverride.Value);
                    }
                    else
                    {
                        attr.DumpTo(writer);
                    }

                    writer.Write("] ");
                }
            }
            else
            {
                foreach (var attr in provider.GetContextualAttributes())
                {
                    writer.Write("[");
                    if (scopeOverride.HasValue)
                    {
                        attr.DumpTo(writer, scopeOverride.Value);
                    }
                    else
                    {
                        attr.DumpTo(writer);
                    }
                    writer.Write("]");
                    writer.WriteLine();
                }
            }
        }
Esempio n. 4
0
        public static void AddDefaultDllImport(CSharpConverter converter, CSharpElement element, CSharpElement context)
        {
            if (!(element is CSharpMethod method) ||
                (method.Modifiers & CSharpModifiers.Extern) == 0 ||
                method.Attributes.OfType <CSharpDllImportAttribute>().Any())
            {
                return;
            }

            var callingConvention   = (method.CppElement as CppFunction)?.CallingConvention ?? CppCallingConvention.Default;
            var csCallingConvention = callingConvention.GetCSharpCallingConvention();
            var name = converter.Options.DefaultDllImportNameAndArguments ?? "LibNativeName";

            method.Attributes.Add(new CSharpDllImportAttribute(name)
            {
                CallingConvention = csCallingConvention
            });
        }
Esempio n. 5
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);
        }
        public static CSharpElement ConvertClass(CSharpConverter converter, CppClass cppClass, CSharpElement context)
        {
            if (cppClass.ClassKind != CppClassKind.Class)
            {
                return(null);
            }
            if (cppClass.Functions.All(x => (x.Flags & CppFunctionFlags.Virtual) == 0))
            {
                return(null);
            }

            // Register the struct as soon as possible
            var csInterfaceName = converter.GetCSharpName(cppClass, context);
            var csInterface     = new CSharpInterface(csInterfaceName)
            {
                CppElement = cppClass,
            };

            var container = converter.GetCSharpContainer(cppClass, context);

            converter.ApplyDefaultVisibility(csInterface, container);
            container.Members.Add(csInterface);

            if (cppClass.BaseTypes.Count > 0)
            {
                var csType = converter.GetCSharpType(cppClass.BaseTypes[0].Type, context);
                csInterface.BaseTypes.Add(csType);
            }

            csInterface.Comment = converter.GetCSharpComment(cppClass, csInterface);

            return(csInterface);
        }
Esempio n. 7
0
        public static string DefaultGetCSharpName(CSharpConverter converter, CppElement element, CSharpElement context)
        {
            var name = string.Empty;

            // Try to get the name directly from the CppElement
            if (element is ICppMember member)
            {
                name = member.Name;
            }

            // If it is null, try to get a contextual name from the context
            if (string.IsNullOrEmpty(name))
            {
                var contextName = string.Empty;
                if (context is ICSharpMember csMember)
                {
                    contextName = csMember.Name;
                }

                if (!string.IsNullOrEmpty(contextName))
                {
                    name = contextName;
                }
            }

            // If the name is null, we create an anonymous type name that includes the type, file name, and file offset
            if (string.IsNullOrEmpty(name))
            {
                var fileName = Path.GetFileNameWithoutExtension(element.Span.Start.File);
                name = $"__Anonymous{element.GetType().Name}_{fileName}_{element.Span.Start.Offset}";
            }
            else if (element is CppType cppType && (!(element is ICppMember cppMember) || string.IsNullOrEmpty(cppMember.Name)))
            {
                switch (cppType)
                {
                case CppClass cppClass:
                    name = CSharpHelper.AppendWithCasing(name, CSharpHelper.GetCSharpCasingKind(name), cppClass.ClassKind.ToString().ToLowerInvariant(), CSharpCasingKind.Lower);
                    break;

                case CppFunctionType cppFunctionType:
                    name = CSharpHelper.AppendWithCasing(name, CSharpHelper.GetCSharpCasingKind(name), "delegate", CSharpCasingKind.Lower);
                    break;
                }
            }

            return(name);
        }
        public static CSharpElement ConvertParameter(CSharpConverter converter, CppParameter cppParam, int index, CSharpElement context)
        {
            var parent     = ((CSharpElement)(context as CSharpMethod) ?? (context as CSharpDelegate));
            var parameters = (context as CSharpMethod)?.Parameters ?? (context as CSharpDelegate)?.Parameters;

            if (parameters == null)
            {
                return(null);
            }

            var csParamName = string.IsNullOrEmpty(cppParam.Name) ? "arg" + index : converter.GetCSharpName(cppParam, context);
            var csParam     = new CSharpParameter(csParamName)
            {
                CppElement = cppParam, Parent = parent
            };

            parameters.Add(csParam);

            var csParamType = converter.GetCSharpType(cppParam.Type, csParam);

            csParam.Index         = index;
            csParam.ParameterType = csParamType;

            return(csParam);
        }
Esempio n. 9
0
        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;
            }
            else
            {
                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, context, csField.FieldType);
                    }
                }

                return csField;
            }
        }
Esempio n. 10
0
        private static void ProcessCSharpElementMappingRules(CSharpConverter converter, CSharpElement element, CSharpElement context)
        {
            if (element.CppElement == null)
            {
                return;
            }

            var cachedRules = GetCachedRules(converter);

            if (cachedRules.ElementToMatches.TryGetValue(element.CppElement, out var rules))
            {
                foreach (var rule in rules)
                {
                    foreach (var action in rule.Rule.CSharpElementActions)
                    {
                        action(converter, element, rule.Matches);
                    }
                }

                // TODO: better try to cache the underlying object
                cachedRules.ElementToMatches.Remove(element.CppElement);
            }
        }
Esempio n. 11
0
        private static void ProcessCppElementMappingRules(CSharpConverter converter, CppElement cppElement, CSharpElement context)
        {
            var cachedRules = GetCachedRules(converter);

            var rules = cachedRules.StandardRules;

            // If a CppElement starts with a Prefix, it was generated by AfterPreprocessing and need to be removed
            // entirely
            if (cppElement is ICppMember member && member.Name.StartsWith(cachedRules.Prefix))
            {
                member.Name = member.Name.Substring(cachedRules.Prefix.Length);
            }

            var matches = new List <ICppElementMatch>();

            foreach (var rule in rules)
            {
                matches.Clear();
                if (rule.Match(cppElement, matches))
                {
                    if (rule.CSharpElementActions.Count > 0)
                    {
                        // save the match for later
                        List <CppElementMatch> listCppElementMatch;
                        if (!cachedRules.ElementToMatches.TryGetValue(cppElement, out listCppElementMatch))
                        {
                            listCppElementMatch = new List <CppElementMatch>();
                            cachedRules.ElementToMatches.Add(cppElement, listCppElementMatch);
                        }
                        listCppElementMatch.Add(new CppElementMatch(rule, new List <ICppElementMatch>(matches)));
                    }

                    foreach (var action in rule.CppElementActions)
                    {
                        action(converter, cppElement, context, matches);
                    }
                }
            }
        }
Esempio n. 12
0
        public static ICSharpContainer GetSharpContainer(CSharpConverter converter, CppElement element, CSharpElement context)
        {
            var cacheContainer = converter.GetTagValueOrDefault <CacheContainer>(CacheContainerKey);

            if (cacheContainer == null)
            {
                cacheContainer = new CacheContainer {
                    DefaultClass = CreateClassLib(converter)
                };
                converter.Tags[CacheContainerKey] = cacheContainer;
            }

            if (converter.Options.DispatchOutputPerInclude)
            {
                var isFromSystemIncludes = converter.IsFromSystemIncludes(element);

                if (!isFromSystemIncludes)
                {
                    var fileName = Path.GetFileNameWithoutExtension(element.Span.Start.File);

                    if (fileName != null)
                    {
                        if (cacheContainer.IncludeToClass.TryGetValue(fileName, out var csClassLib))
                        {
                            return(csClassLib);
                        }

                        csClassLib = CreateClassLib(converter, UPath.Combine(UPath.Root, fileName + ".generated.cs"));
                        cacheContainer.IncludeToClass.Add(fileName, csClassLib);
                        return(csClassLib);
                    }
                }
            }

            return(cacheContainer.DefaultClass);
        }
Esempio n. 13
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);
        }
        public static CSharpElement ConvertFunction(CSharpConverter converter, CppFunction cppFunction, CSharpElement context)
        {
            // We process only public export functions
            if (!cppFunction.IsPublicExport() || ((cppFunction.Flags & (CppFunctionFlags.Inline | CppFunctionFlags.Method | CppFunctionFlags.Constructor | CppFunctionFlags.Destructor)) != 0 && (cppFunction.Flags & CppFunctionFlags.Virtual) == 0))
            {
                return(null);
            }

            // Register the struct as soon as possible
            var csFunction = new CSharpMethod()
            {
                CppElement = cppFunction
            };

            var container = converter.GetCSharpContainer(cppFunction, context);

            converter.ApplyDefaultVisibility(csFunction, container);
            container.Members.Add(csFunction);

            converter.AddUsing(container, "System.Runtime.InteropServices");

            if ((cppFunction.Flags & CppFunctionFlags.Virtual) == 0)
            {
                csFunction.Modifiers |= CSharpModifiers.Static | CSharpModifiers.Extern;
            }
            else
            {
                csFunction.Visibility = CSharpVisibility.None;
            }
            csFunction.Name       = converter.GetCSharpName(cppFunction, csFunction);
            csFunction.Comment    = converter.GetCSharpComment(cppFunction, csFunction);
            csFunction.ReturnType = converter.GetCSharpType(cppFunction.ReturnType, csFunction);

            return(csFunction);
        }
Esempio n. 15
0
        public static CSharpType GetCSharpType(CSharpConverter converter, CppType cppType, CSharpElement context, bool nested)
        {
            // Early exit for primitive types
            if (cppType is CppPrimitiveType cppPrimitiveType)
            {
                // Special case for bool
                return(cppPrimitiveType.Kind == CppPrimitiveKind.Bool
                    ? GetBoolType(converter)
                    : CSharpHelper.GetCSharpPrimitive(cppPrimitiveType));
            }

            // Check if a particular CppType has been already converted
            var csType = converter.FindCSharpType(cppType);

            if (csType != null)
            {
                return(csType);
            }

            // Pre-decode the type by extracting any const/pointer and get the element type directly
            DecodeSimpleType(cppType, out var isConst, out var isPointer, out var elementType);

            if (isPointer)
            {
                if (isConst && elementType.Equals(CppPrimitiveType.Char))
                {
                    // const char* => string (with marshal)
                    csType = GetStringType(converter);
                }
                else
                {
                    var pointedCSharpType = converter.GetCSharpType(elementType, context, true);

                    var isParam  = context is CSharpParameter;
                    var isReturn = context is CSharpMethod;
                    if (!nested && (isParam || isReturn))
                    {
                        switch (elementType.TypeKind)
                        {
                        case CppTypeKind.Array:
                            break;

                        case CppTypeKind.Reference:
                            break;

                        case CppTypeKind.Qualified:
                            var qualifiedType = (CppQualifiedType)elementType;
                            csType = new CSharpRefType(qualifiedType.Qualifier == CppTypeQualifier.Const ? (isParam ? CSharpRefKind.In : CSharpRefKind.RefReadOnly) : CSharpRefKind.Ref, converter.GetCSharpType(qualifiedType.ElementType, context, true));
                            break;

                        case CppTypeKind.Function:
                            csType = pointedCSharpType;
                            break;

                        case CppTypeKind.Typedef:
                            csType = new CSharpRefType(CSharpRefKind.Ref, pointedCSharpType);
                            break;

                        case CppTypeKind.StructOrClass:
                            // Is the struct is an opaque definition (which can is transformed into passing the struct directly as
                            // the struct contains the pointer)
                            if (pointedCSharpType is CSharpStruct csStruct && csStruct.IsOpaque)
                            {
                                csType = csStruct;
                            }
                            else
                            {
                                csType = new CSharpRefType(isConst ? (isParam ? CSharpRefKind.In : CSharpRefKind.RefReadOnly) : CSharpRefKind.Ref, pointedCSharpType);
                            }
                            break;
        public static CSharpComment ConvertComment(CSharpConverter converter, CppElement element, CSharpElement context)
        {
            if (!(element is ICppDeclaration cppDecl))
            {
                return(null);
            }

            var comment = cppDecl.Comment;

            if (comment?.Children == null)
            {
                return(null);
            }

            var csFullComment = new CSharpFullComment();

            CSharpXmlComment csRemarks = null;

            for (var i = 0; i < comment.Children.Count; i++)
            {
                var childComment = comment.Children[i];
                if (i == 0)
                {
                    var summary = new CSharpXmlComment("summary");
                    summary.Children.Add(GetAsCSharpComment(childComment));
                    csFullComment.Children.Add(summary);
                    continue;
                }

                switch (childComment.Kind)
                {
                case CppCommentKind.ParamCommand:
                    var paramComment = (CppCommentParamCommand)childComment;

                    var csParamComment = new CSharpParamComment(paramComment.ParamName);
                    csParamComment.Children.Add(GetChildAsCSharpComment(paramComment));
                    csFullComment.Children.Add(csParamComment);
                    break;

                case CppCommentKind.BlockCommand:
                    var blockCommand = (CppCommentBlockCommand)childComment;
                    if (blockCommand.CommandName == "return")
                    {
                        var returnComment = new CSharpReturnComment();
                        returnComment.Children.Add(GetChildAsCSharpComment(blockCommand));
                        csFullComment.Children.Add(returnComment);
                    }
                    else if (blockCommand.CommandName == "see")
                    {
                        var seealso = new CSharpXmlComment("seealso")
                        {
                            IsSelfClosing = true
                        };
                        seealso.Attributes.Add(new CSharpXmlAttribute("cref", GetChildAsText(childComment)));
                        csFullComment.Children.Add(seealso);
                    }
                    else
                    {
                        if (csRemarks == null)
                        {
                            csRemarks = new CSharpXmlComment("remarks");
                        }
                        AddComment(csRemarks, childComment);
                    }
                    break;

                default:
                    if (csRemarks == null)
                    {
                        csRemarks = new CSharpXmlComment("remarks");
                    }
                    AddComment(csRemarks, childComment);
                    break;
                }
            }

            if (csRemarks != null && csRemarks.Children.Count > 0)
            {
                csFullComment.Children.Add(csRemarks);
            }

            return(csFullComment);
        }