コード例 #1
0
        static int GetValueTypeSize(Type type, List <Type> fieldTypes, bool is_64_bits)
        {
            int size           = 0;
            int maxElementSize = 1;

            if (type.IsExplicitLayout)
            {
                // Find the maximum of "field size + field offset" for each field.
                foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
#if BGENERATOR
                    var fieldOffset = AttributeManager.GetCustomAttribute <FieldOffsetAttribute> (field);
#else
                    var fieldOffset = (FieldOffsetAttribute)Attribute.GetCustomAttribute(field, typeof(FieldOffsetAttribute));
#endif
                    var elementSize = 0;
                    GetValueTypeSize(type, field.FieldType, fieldTypes, is_64_bits, ref elementSize, ref maxElementSize);
                    size = Math.Max(size, elementSize + fieldOffset.Value);
                }
            }
            else
            {
                GetValueTypeSize(type, type, fieldTypes, is_64_bits, ref size, ref maxElementSize);
            }

            if (size % maxElementSize != 0)
            {
                size += (maxElementSize - size % maxElementSize);
            }

            return(size);
        }
コード例 #2
0
    public void GenerateFilter(Type type)
    {
        var is_abstract = AttributeManager.HasAttribute <AbstractAttribute> (type);
        var filter      = AttributeManager.GetCustomAttribute <CoreImageFilterAttribute> (type);
        var base_type   = AttributeManager.GetCustomAttribute <BaseTypeAttribute> (type);
        var type_name   = type.Name;
        var native_name = base_type.Name ?? type_name;
        var base_name   = base_type.BaseType.Name;

        // internal static CIFilter FromName (string filterName, IntPtr handle)
        filters.Add(type_name);

        // type declaration
        print("public{0} partial class {1} : {2} {{",
              is_abstract ? " abstract" : String.Empty,
              type_name, base_name);
        print("");
        indent++;

        // default constructor - if type is not abstract
        string v;

        if (!is_abstract)
        {
            v = GetVisibility(filter.DefaultCtorVisibility);
            if (v.Length > 0)
            {
                print_generated_code();
                print("{0}{1} () : base (\"{2}\")", v, type.Name, native_name);
                PrintEmptyBody();
            }
        }

        // IntPtr constructor - always present
        var intptrctor_visibility = filter.IntPtrCtorVisibility;

        if (intptrctor_visibility == MethodAttributes.PrivateScope)
        {
            // since it was not generated code we never fixed the .ctor(IntPtr) visibility for unified
            if (Generator.XamcoreVersion >= 3)
            {
                intptrctor_visibility = MethodAttributes.FamORAssem;
            }
            else
            {
                intptrctor_visibility = MethodAttributes.Public;
            }
        }
        print_generated_code();
        print("{0}{1} (IntPtr handle) : base (handle)", GetVisibility(intptrctor_visibility), type_name);
        PrintEmptyBody();

        // NSObjectFlag constructor - always present (needed to implement NSCoder for subclasses)
        print_generated_code();
        print("[EditorBrowsable (EditorBrowsableState.Advanced)]");
        print("protected {0} (NSObjectFlag t) : base (t)", type_name);
        PrintEmptyBody();

        // NSCoder constructor - all filters conforms to NSCoding
        print_generated_code();
        print("[EditorBrowsable (EditorBrowsableState.Advanced)]");
        print("[Export (\"initWithCoder:\")]");
        print("public {0} (NSCoder coder) : base (NSObjectFlag.Empty)", type_name);
        print("{");
        indent++;
        print("IntPtr h;");
        print("if (IsDirectBinding) {");
        indent++;
        print("h = global::{0}.Messaging.IntPtr_objc_msgSend_IntPtr (this.Handle, Selector.GetHandle (\"initWithCoder:\"), coder.Handle);", ns.CoreObjCRuntime);
        indent--;
        print("} else {");
        indent++;
        print("h = global::{0}.Messaging.IntPtr_objc_msgSendSuper_IntPtr (this.SuperHandle, Selector.GetHandle (\"initWithCoder:\"), coder.Handle);", ns.CoreObjCRuntime);
        indent--;
        print("}");
        print("InitializeHandle (h, \"initWithCoder:\");");
        indent--;
        print("}");
        print("");

        // string constructor
        // default is protected (for abstract) but backward compatibility (XAMCORE_2_0) requires some hacks
        v = GetVisibility(filter.StringCtorVisibility);
        if (is_abstract && (v.Length == 0))
        {
            v = "protected ";
        }
        if (v.Length > 0)
        {
            print_generated_code();
            print("{0} {1} (string name) : base (CreateFilter (name))", v, type_name);
            PrintEmptyBody();
        }

        // properties
        foreach (var p in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (p.IsUnavailable())
            {
                continue;
            }

            print("");
            print_generated_code();
            var ptype = p.PropertyType.Name;
            // keep C# names as they are reserved keywords (e.g. Boolean also exists in OpenGL for Mac)
            switch (ptype)
            {
            case "Boolean":
                ptype = "bool";
                break;

            case "Int32":
                ptype = "int";
                break;

            case "Single":
                ptype = "float";
                break;

            case "String":
                ptype = "string";
                break;
            }
            print("public {0} {1} {{", ptype, p.Name);
            indent++;

            var name = AttributeManager.GetCustomAttribute <CoreImageFilterPropertyAttribute> (p)?.Name;
            if (p.GetGetMethod() != null)
            {
                GenerateFilterGetter(ptype, name);
            }
            if (p.GetSetMethod() != null)
            {
                GenerateFilterSetter(ptype, name);
            }

            indent--;
            print("}");
        }

        indent--;
        print("}");

        // namespace closing (it's optional to use namespaces even if it's a bad practice, ref #35283)
        if (indent > 0)
        {
            indent--;
            print("}");
        }
    }
コード例 #3
0
    // caller already:
    //	- setup the header and namespace
    //	- call/emit PrintPlatformAttributes on the type
    void GenerateEnum(Type type)
    {
        if (AttributeManager.HasAttribute <FlagsAttribute> (type))
        {
            print("[Flags]");
        }

        var native = AttributeManager.GetCustomAttribute <NativeAttribute> (type);

        if (native != null)
        {
            if (String.IsNullOrEmpty(native.NativeName))
            {
                print("[Native]");
            }
            else
            {
                print("[Native (\"{0}\")]", native.NativeName);
            }
        }
        CopyObsolete(type);

        var unique_constants = new HashSet <string> ();
        var fields           = new Dictionary <FieldInfo, FieldAttribute> ();
        Tuple <FieldInfo, FieldAttribute> null_field     = null;
        Tuple <FieldInfo, FieldAttribute> default_symbol = null;
        var underlying_type = GetCSharpTypeName(TypeManager.GetUnderlyingEnumType(type));

        print("public enum {0} : {1} {{", type.Name, underlying_type);
        indent++;
        foreach (var f in type.GetFields())
        {
            // skip value__ field
            if (f.IsSpecialName)
            {
                continue;
            }
            PrintPlatformAttributes(f);
            CopyObsolete(f);
            print("{0} = {1},", f.Name, f.GetRawConstantValue());
            var fa = AttributeManager.GetCustomAttribute <FieldAttribute> (f);
            if (fa == null)
            {
                continue;
            }
            if (f.IsUnavailable())
            {
                continue;
            }
            if (fa.SymbolName == null)
            {
                null_field = new Tuple <FieldInfo, FieldAttribute> (f, fa);
            }
            else if (unique_constants.Contains(fa.SymbolName))
            {
                throw new BindingException(1046, true, $"The [Field] constant {fa.SymbolName} cannot only be used once inside enum {type.Name}.");
            }
            else
            {
                fields.Add(f, fa);
                unique_constants.Add(fa.SymbolName);
            }
            if (AttributeManager.GetCustomAttribute <DefaultEnumValueAttribute> (f) != null)
            {
                if (default_symbol != null)
                {
                    throw new BindingException(1045, true, $"Only a single [DefaultEnumValue] attribute can be used inside enum {type.Name}.");
                }
                default_symbol = new Tuple <FieldInfo, FieldAttribute> (f, fa);
            }
        }
        indent--;
        print("}");
        unique_constants.Clear();

        var library_name = type.Namespace;
        var error        = AttributeManager.GetCustomAttribute <ErrorDomainAttribute> (type);

        if ((fields.Count > 0) || (error != null))
        {
            print("");
            // the *Extensions has the same version requirement as the enum itself
            PrintPlatformAttributes(type);
            print("[CompilerGenerated]");
            print("static public partial class {0}Extensions {{", type.Name);
            indent++;

            var field     = fields.FirstOrDefault();
            var fieldAttr = field.Value;

            ComputeLibraryName(fieldAttr, type, field.Key?.Name, out library_name, out string library_path);
        }

        if (error != null)
        {
            // this attribute is important for our tests
            print("[Field (\"{0}\", \"{1}\")]", error.ErrorDomain, library_name);
            print("static NSString _domain;");
            print("");
            print("public static NSString GetDomain (this {0} self)", type.Name);
            print("{");
            indent++;
            print("if (_domain == null)");
            indent++;
            print("_domain = Dlfcn.GetStringConstant (Libraries.{0}.Handle, \"{1}\");", library_name, error.ErrorDomain);
            indent--;
            print("return _domain;");
            indent--;
            print("}");
        }

        if (fields.Count > 0)
        {
            print("static IntPtr[] values = new IntPtr [{0}];", fields.Count);
            print("");

            int n = 0;
            foreach (var kvp in fields)
            {
                var f  = kvp.Key;
                var fa = kvp.Value;
                // the attributes (availability and field) are important for our tests
                PrintPlatformAttributes(f);
                libraries.TryGetValue(library_name, out var libPath);
                var libname = fa.LibraryName?.Replace("+", string.Empty);
                // We need to check for special cases inside FieldAttributes
                // fa.LibraryName could contain a different framework i.e UITrackingRunLoopMode (UIKit) inside NSRunLoopMode enum (Foundation).
                // libPath could have a custom path i.e. CoreImage which in macOS is inside Quartz
                // library_name contains the Framework constant name the Field is inside of, used as fallback.
                bool useFieldAttrLibName = libname != null && !string.Equals(libname, library_name, StringComparison.OrdinalIgnoreCase);
                print("[Field (\"{0}\", \"{1}\")]", fa.SymbolName, useFieldAttrLibName ? libname : libPath ?? library_name);
                print("internal unsafe static IntPtr {0} {{", fa.SymbolName);
                indent++;
                print("get {");
                indent++;
                print("fixed (IntPtr *storage = &values [{0}])", n++);
                indent++;
                print("return Dlfcn.CachePointer (Libraries.{0}.Handle, \"{1}\", storage);", useFieldAttrLibName ? libname : library_name, fa.SymbolName);
                indent--;
                indent--;
                print("}");
                indent--;
                print("}");
                print("");
            }

            print("public static NSString GetConstant (this {0} self)", type.Name);
            print("{");
            indent++;
            print("IntPtr ptr = IntPtr.Zero;");
            print("switch (({0}) self) {{", underlying_type);
            var default_symbol_name = default_symbol?.Item2.SymbolName;
            // more than one enum member can share the same numeric value - ref: #46285
            foreach (var kvp in fields)
            {
                print("case {0}: // {1}.{2}", Convert.ToInt64(kvp.Key.GetRawConstantValue()), type.Name, kvp.Key.Name);
                var sn = kvp.Value.SymbolName;
                if (sn == default_symbol_name)
                {
                    print("default:");
                }
                indent++;
                print("ptr = {0};", sn);
                print("break;");
                indent--;
            }
            print("}");
            print("return (NSString) Runtime.GetNSObject (ptr);");
            indent--;
            print("}");

            print("");

            print("public static {0} GetValue (NSString constant)", type.Name);
            print("{");
            indent++;
            print("if (constant == null)");
            indent++;
            // if we do not have a enum value that maps to a null field then we throw
            if (null_field == null)
            {
                print("throw new ArgumentNullException (nameof (constant));");
            }
            else
            {
                print("return {0}.{1};", type.Name, null_field.Item1.Name);
            }
            indent--;
            foreach (var kvp in fields)
            {
                print("if (constant.IsEqualTo ({0}))", kvp.Value.SymbolName);
                indent++;
                print("return {0}.{1};", type.Name, kvp.Key.Name);
                indent--;
            }
            // if there's no default then we throw on unknown constants
            if (default_symbol == null)
            {
                print("throw new NotSupportedException (constant + \" has no associated enum value in \" + nameof ({0}) + \" on this platform.\");", type.Name);
            }
            else
            {
                print("return {0}.{1};", type.Name, default_symbol.Item1.Name);
            }
            indent--;
            print("}");
        }

        if ((fields.Count > 0) || (error != null))
        {
            indent--;
            print("}");
        }

        // namespace closing (it's optional to use namespaces even if it's a bad practice, ref #35283)
        if (indent > 0)
        {
            indent--;
            print("}");
        }
    }
コード例 #4
0
    public void GenerateFilter(Type type)
    {
        var is_abstract = AttributeManager.HasAttribute <AbstractAttribute> (type);
        var filter      = AttributeManager.GetCustomAttribute <CoreImageFilterAttribute> (type);
        var base_type   = AttributeManager.GetCustomAttribute <BaseTypeAttribute> (type);
        var type_name   = type.Name;
        var native_name = base_type.Name ?? type_name;
        var base_name   = base_type.BaseType.Name;

        // internal static CIFilter FromName (string filterName, IntPtr handle)
        filters.Add(type_name);

        // filters are now exposed as protocols so we need to conform to them
        var interfaces = String.Empty;

        foreach (var i in type.GetInterfaces())
        {
            interfaces += $", I{i.Name}";
        }

        // type declaration
        print("public{0} partial class {1} : {2}{3} {{",
              is_abstract ? " abstract" : String.Empty,
              type_name, base_name, interfaces);
        print("");
        indent++;

        // default constructor - if type is not abstract
        string v;

        if (!is_abstract)
        {
            v = GetVisibility(filter.DefaultCtorVisibility);
            if (v.Length > 0)
            {
                print_generated_code();
                print("{0}{1} () : base (\"{2}\")", v, type.Name, native_name);
                PrintEmptyBody();
            }
        }

        // IntPtr constructor - always present
        var intptrctor_visibility = filter.IntPtrCtorVisibility;

        if (intptrctor_visibility == MethodAttributes.PrivateScope)
        {
            // since it was not generated code we never fixed the .ctor(IntPtr) visibility for unified
            if (XamcoreVersion >= 3)
            {
                intptrctor_visibility = MethodAttributes.FamORAssem;
            }
            else
            {
                intptrctor_visibility = MethodAttributes.Public;
            }
        }
        print_generated_code();
        print("{0}{1} (IntPtr handle) : base (handle)", GetVisibility(intptrctor_visibility), type_name);
        PrintEmptyBody();

        // NSObjectFlag constructor - always present (needed to implement NSCoder for subclasses)
        print_generated_code();
        print("[EditorBrowsable (EditorBrowsableState.Advanced)]");
        print("protected {0} (NSObjectFlag t) : base (t)", type_name);
        PrintEmptyBody();

        // NSCoder constructor - all filters conforms to NSCoding
        print_generated_code();
        print("[EditorBrowsable (EditorBrowsableState.Advanced)]");
        print("[Export (\"initWithCoder:\")]");
        print("public {0} (NSCoder coder) : base (NSObjectFlag.Empty)", type_name);
        print("{");
        indent++;
        print("IntPtr h;");
        print("if (IsDirectBinding) {");
        indent++;
        print("h = global::{0}.Messaging.IntPtr_objc_msgSend_IntPtr (this.Handle, Selector.GetHandle (\"initWithCoder:\"), coder.Handle);", ns.CoreObjCRuntime);
        indent--;
        print("} else {");
        indent++;
        print("h = global::{0}.Messaging.IntPtr_objc_msgSendSuper_IntPtr (this.SuperHandle, Selector.GetHandle (\"initWithCoder:\"), coder.Handle);", ns.CoreObjCRuntime);
        indent--;
        print("}");
        print("InitializeHandle (h, \"initWithCoder:\");");
        indent--;
        print("}");
        print("");

        // string constructor
        // default is protected (for abstract) but backward compatibility (XAMCORE_2_0) requires some hacks
        v = GetVisibility(filter.StringCtorVisibility);
        if (is_abstract && (v.Length == 0))
        {
            v = "protected ";
        }
        if (v.Length > 0)
        {
            print_generated_code();
            print("{0} {1} (string name) : base (CreateFilter (name))", v, type_name);
            PrintEmptyBody();
        }

        // properties
        GenerateProperties(type);

        // protocols
        GenerateProtocolProperties(type, new HashSet <string> ());

        indent--;
        print("}");

        // namespace closing (it's optional to use namespaces even if it's a bad practice, ref #35283)
        if (indent > 0)
        {
            indent--;
            print("}");
        }
    }
コード例 #5
0
    void GenerateProperties(Type type)
    {
        foreach (var p in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (p.IsUnavailable(this))
            {
                continue;
            }
            if (AttributeManager.HasAttribute <StaticAttribute> (p))
            {
                continue;
            }

            print("");
            PrintPropertyAttributes(p);
            print_generated_code();

            var ptype = p.PropertyType.Name;
            // keep C# names as they are reserved keywords (e.g. Boolean also exists in OpenGL for Mac)
            switch (ptype)
            {
            case "Boolean":
                ptype = "bool";
                break;

            case "Int32":
                ptype = "int";
                break;

            case "Single":
                ptype = "float";
                break;

            case "String":
                ptype = "string";
                break;

            // adding `using ImageIO;` would lead to `error CS0104: 'CGImageProperties' is an ambiguous reference between 'CoreGraphics.CGImageProperties' and 'ImageIO.CGImageProperties'`
            case "CGImageMetadata":
                ptype = "ImageIO.CGImageMetadata";
                break;
            }
            print("public {0} {1} {{", ptype, p.Name);
            indent++;

            // an export will be present (only) if it's defined in a protocol
            var export = AttributeManager.GetCustomAttribute <ExportAttribute> (p);

            var name = AttributeManager.GetCustomAttribute <CoreImageFilterPropertyAttribute> (p)?.Name;
            // we can skip the name when it's identical to a protocol selector
            if (name == null)
            {
                if (export == null)
                {
                    throw new BindingException(1072, true, $"Missing [CoreImageFilterProperty] attribute on {0} property {1}", type.Name, p.Name);
                }

                var sel = export.Selector;
                if (sel.StartsWith("input", StringComparison.Ordinal))
                {
                    name = sel;
                }
                else
                {
                    name = "input" + Capitalize(sel);
                }
            }

            if (p.GetGetMethod() != null)
            {
                PrintFilterExport(p, export, setter: false);
                GenerateFilterGetter(ptype, name);
            }
            if (p.GetSetMethod() != null)
            {
                PrintFilterExport(p, export, setter: true);
                GenerateFilterSetter(ptype, name);
            }

            indent--;
            print("}");
        }
    }
コード例 #6
0
    void GenerateProperties(Type type, Type originalType = null, bool fromProtocol = false)
    {
        foreach (var p in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (p.IsUnavailable(this))
            {
                continue;
            }
            if (AttributeManager.HasAttribute <StaticAttribute> (p))
            {
                continue;
            }

            print("");

            // an export will be present (only) if it's defined in a protocol
            var export = AttributeManager.GetCustomAttribute <ExportAttribute> (p);

            // this is a bit special since CoreImage filter protocols are much newer than the our generated, key-based bindings
            // so we do not want to advertise the protocol versions since most properties would be incorrectly advertised
            PrintPropertyAttributes(p, originalType, skipTypeInjection: export != null);
            print_generated_code();

            var ptype    = p.PropertyType.Name;
            var nullable = false;
            // keep C# names as they are reserved keywords (e.g. Boolean also exists in OpenGL for Mac)
            switch (ptype)
            {
            case "Boolean":
                ptype = "bool";
                break;

            case "Int32":
                ptype = "int";
                break;

            case "Single":
                ptype = "float";
                break;

            case "String":
                ptype = "string";
                break;

            // adding `using ImageIO;` would lead to `error CS0104: 'CGImageProperties' is an ambiguous reference between 'CoreGraphics.CGImageProperties' and 'ImageIO.CGImageProperties'`
            case "CGImageMetadata":
                ptype = "ImageIO.CGImageMetadata";
                break;

            case "CIVector":
            case "CIColor":
            case "CIImage":
                // protocol-based bindings have annotations - but the older, key-based, versions did not
                if (!fromProtocol)
                {
                    nullable = true;
                }
                break;
            }
            if (AttributeManager.HasAttribute <NullAllowedAttribute> (p))
            {
                nullable = true;
            }
            print("public {0}{1} {2} {{", ptype, nullable ? "?" : "", p.Name);
            indent++;

            var name = AttributeManager.GetCustomAttribute <CoreImageFilterPropertyAttribute> (p)?.Name;
            // we can skip the name when it's identical to a protocol selector
            if (name == null)
            {
                if (export == null)
                {
                    throw new BindingException(1074, true, type.Name, p.Name);
                }

                var sel = export.Selector;
                if (sel.StartsWith("input", StringComparison.Ordinal))
                {
                    name = sel;
                }
                else
                {
                    name = "input" + Capitalize(sel);
                }
            }

            if (p.GetGetMethod() != null)
            {
                PrintFilterExport(p, export, setter: false);
                GenerateFilterGetter(ptype, name);
            }
            if (p.GetSetMethod() != null)
            {
                PrintFilterExport(p, export, setter: true);
                GenerateFilterSetter(ptype, name);
            }

            indent--;
            print("}");
        }
    }
コード例 #7
0
        static void GetValueTypeSize(Type original_type, Type type, List <Type> field_types, bool is_64_bits, ref int size, ref int max_element_size)
        {
            // FIXME:
            // SIMD types are not handled correctly here (they need 16-bit alignment).
            // However we don't annotate those types in any way currently, so first we'd need to
            // add the proper attributes so that the generator can distinguish those types from other types.

            var type_size = 0;

            switch (type.FullName)
            {
            case "System.Char":
            case "System.Boolean":
            case "System.SByte":
            case "System.Byte":
                type_size = 1;
                break;

            case "System.Int16":
            case "System.UInt16":
                type_size = 2;
                break;

            case "System.Single":
            case "System.Int32":
            case "System.UInt32":
                type_size = 4;
                break;

            case "System.Double":
            case "System.Int64":
            case "System.UInt64":
                type_size = 8;
                break;

            case "System.IntPtr":
            case "System.nfloat":
            case "System.nuint":
            case "System.nint":
                type_size = is_64_bits ? 8 : 4;
                break;
            }

            if (type_size != 0)
            {
                field_types.Add(type);
                size = AlignAndAdd(original_type, size, type_size, ref max_element_size);
                return;
            }

            // composite struct
            foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
#if BGENERATOR
                var marshalAs = AttributeManager.GetCustomAttribute <MarshalAsAttribute> (field);
#else
                var marshalAs = (MarshalAsAttribute)Attribute.GetCustomAttribute(field, typeof(MarshalAsAttribute));
#endif
                if (marshalAs == null)
                {
                    GetValueTypeSize(original_type, field.FieldType, field_types, is_64_bits, ref size, ref max_element_size);
                    continue;
                }

                var multiplier = 1;
                switch (marshalAs.Value)
                {
                case UnmanagedType.ByValArray:
                    var types = new List <Type> ();
                    GetValueTypeSize(original_type, field.FieldType.GetElementType(), types, is_64_bits, ref type_size, ref max_element_size);
                    multiplier = marshalAs.SizeConst;
                    break;

                case UnmanagedType.U1:
                case UnmanagedType.I1:
                    type_size = 1;
                    break;

                case UnmanagedType.U2:
                case UnmanagedType.I2:
                    type_size = 2;
                    break;

                case UnmanagedType.U4:
                case UnmanagedType.I4:
                case UnmanagedType.R4:
                    type_size = 4;
                    break;

                case UnmanagedType.U8:
                case UnmanagedType.I8:
                case UnmanagedType.R8:
                    type_size = 8;
                    break;

                default:
                    throw new Exception($"Unhandled MarshalAs attribute: {marshalAs.Value} on field {field.DeclaringType.FullName}.{field.Name}");
                }
                field_types.Add(field.FieldType);
                size  = AlignAndAdd(original_type, size, type_size, ref max_element_size);
                size += (multiplier - 1) * size;
            }
        }