Пример #1
0
        private static ClassInfo GetClassInfo(Type type)
        {
            ClassInfo ci = new ClassInfo(type);
            Hashtable methods = new Hashtable();
            ArrayList list;
            MethodInfo meth;
            ManagedType ob;
            String name;
            Object item;
            Type tp;
            int i, n;

            // This is complicated because inheritance in Python is name
            // based. We can't just find DeclaredOnly members, because we
            // could have a base class A that defines two overloads of a
            // method and a class B that defines two more. The name-based
            // descriptor Python will find needs to know about inherited
            // overloads as well as those declared on the sub class.

            BindingFlags flags = BindingFlags.Static |
                                 BindingFlags.Instance |
                                 BindingFlags.Public |
                                 BindingFlags.NonPublic;

            MemberInfo[] info = type.GetMembers(flags);
            Hashtable local = new Hashtable();
            ArrayList items = new ArrayList();
            MemberInfo m;

            // Loop through once to find out which names are declared
            for (i = 0; i < info.Length; i++)
            {
                m = info[i];
                if (m.DeclaringType == type)
                {
                    local[m.Name] = 1;
                }
            }

            // Now again to filter w/o losing overloaded member info
            for (i = 0; i < info.Length; i++)
            {
                m = info[i];
                if (local[m.Name] != null)
                {
                    items.Add(m);
                }
            }

            if (type.IsInterface)
            {
                // Interface inheritance seems to be a different animal:
                // more contractual, less structural.  Thus, a Type that
                // represents an interface that inherits from another
                // interface does not return the inherited interface's
                // methods in GetMembers. For example ICollection inherits
                // from IEnumerable, but ICollection's GetMemebers does not
                // return GetEnumerator.
                //
                // Not sure if this is the correct way to fix this, but it
                // seems to work. Thanks to Bruce Dodson for the fix.

                Type[] inheritedInterfaces = type.GetInterfaces();

                for (i = 0; i < inheritedInterfaces.Length; ++i)
                {
                    Type inheritedType = inheritedInterfaces[i];
                    MemberInfo[] imembers = inheritedType.GetMembers(flags);
                    for (n = 0; n < imembers.Length; n++)
                    {
                        m = imembers[n];
                        if (local[m.Name] == null)
                        {
                            items.Add(m);
                        }
                    }
                }
            }

            for (i = 0; i < items.Count; i++)
            {
                MemberInfo mi = (MemberInfo)items[i];

                switch (mi.MemberType)
                {
                    case MemberTypes.Method:
                        meth = (MethodInfo)mi;
                        if (!(meth.IsPublic || meth.IsFamily ||
                              meth.IsFamilyOrAssembly))
                            continue;
                        name = meth.Name;
                        item = methods[name];
                        if (item == null)
                        {
                            item = methods[name] = new ArrayList();
                        }
                        list = (ArrayList)item;
                        list.Add(meth);
                        continue;

                    case MemberTypes.Property:
                        PropertyInfo pi = (PropertyInfo)mi;

                        MethodInfo mm = null;
                        try
                        {
                            mm = pi.GetGetMethod(true);
                            if (mm == null)
                            {
                                mm = pi.GetSetMethod(true);
                            }
                        }
                        catch (SecurityException)
                        {
                            // GetGetMethod may try to get a method protected by
                            // StrongNameIdentityPermission - effectively private.
                            continue;
                        }

                        if (mm == null)
                        {
                            continue;
                        }

                        if (!(mm.IsPublic || mm.IsFamily || mm.IsFamilyOrAssembly))
                            continue;

                        // Check for indexer
                        ParameterInfo[] args = pi.GetIndexParameters();
                        if (args.GetLength(0) > 0)
                        {
                            Indexer idx = ci.indexer;
                            if (idx == null)
                            {
                                ci.indexer = new Indexer();
                                idx = ci.indexer;
                            }
                            idx.AddProperty(pi);
                            continue;
                        }

                        ob = new PropertyObject(pi);
                        ci.members[pi.Name] = ob;
                        continue;

                    case MemberTypes.Field:
                        FieldInfo fi = (FieldInfo)mi;
                        if (!(fi.IsPublic || fi.IsFamily || fi.IsFamilyOrAssembly))
                            continue;
                        ob = new FieldObject(fi);
                        ci.members[mi.Name] = ob;
                        continue;

                    case MemberTypes.Event:
                        EventInfo ei = (EventInfo)mi;
                        MethodInfo me = ei.GetAddMethod(true);
                        if (!(me.IsPublic || me.IsFamily || me.IsFamilyOrAssembly))
                            continue;
                        ob = new EventObject(ei);
                        ci.members[ei.Name] = ob;
                        continue;

                    case MemberTypes.NestedType:
                        tp = (Type)mi;
                        if (!(tp.IsNestedPublic || tp.IsNestedFamily ||
                              tp.IsNestedFamORAssem))
                            continue;
                        // Note the given instance might be uninitialized
                        ob = ClassManager.GetClass(tp);
                        ci.members[mi.Name] = ob;
                        continue;
                }
            }

            IDictionaryEnumerator iter = methods.GetEnumerator();

            while (iter.MoveNext())
            {
                name = (string)iter.Key;
                list = (ArrayList)iter.Value;

                MethodInfo[] mlist = (MethodInfo[])list.ToArray(
                    typeof(MethodInfo)
                    );

                ob = new MethodObject(type, name, mlist);
                ci.members[name] = ob;
            }

            return ci;
        }
Пример #2
0
        private static void InitClassBase(Type type, ClassBase impl)
        {
            // Ensure, that matching Python type exists first.
            // It is required for self-referential classes
            // (e.g. with members, that refer to the same class)
            var pyType = TypeManager.GetOrCreateClass(type);

            // Set the handle attributes on the implementing instance.
            impl.tpHandle = impl.pyHandle = pyType.Handle;

            // First, we introspect the managed type and build some class
            // information, including generating the member descriptors
            // that we'll be putting in the Python class __dict__.

            ClassInfo info = GetClassInfo(type);

            impl.indexer     = info.indexer;
            impl.richcompare = new Dictionary <int, MethodObject>();

            // Now we force initialize the Python type object to reflect the given
            // managed type, filling the Python type slots with thunks that
            // point to the managed methods providing the implementation.


            TypeManager.GetOrInitializeClass(impl, type);

            // Finally, initialize the class __dict__ and return the object.
            using var dict = Runtime.PyObject_GenericGetDict(pyType.Reference);


            if (impl.dotNetMembers == null)
            {
                impl.dotNetMembers = new List <string>();
            }
            IDictionaryEnumerator iter = info.members.GetEnumerator();

            while (iter.MoveNext())
            {
                var item = (ManagedType)iter.Value;
                var name = (string)iter.Key;
                impl.dotNetMembers.Add(name);
                Runtime.PyDict_SetItemString(dict, name, item.ObjectReference);
                // Decref the item now that it's been used.
                item.DecrRefCount();
                if (ClassBase.CilToPyOpMap.TryGetValue(name, out var pyOp))
                {
                    impl.richcompare.Add(pyOp, (MethodObject)item);
                }
            }

            // If class has constructors, generate an __doc__ attribute.
            NewReference doc    = default;
            Type         marker = typeof(DocStringAttribute);
            var          attrs  = (Attribute[])type.GetCustomAttributes(marker, false);

            if (attrs.Length != 0)
            {
                var    attr   = (DocStringAttribute)attrs[0];
                string docStr = attr.DocString;
                doc = NewReference.DangerousFromPointer(Runtime.PyString_FromString(docStr));
                Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc);
            }

            var co = impl as ClassObject;

            // If this is a ClassObject AND it has constructors, generate a __doc__ attribute.
            // required that the ClassObject.ctors be changed to internal
            if (co != null)
            {
                if (co.NumCtors > 0)
                {
                    // Implement Overloads on the class object
                    if (!CLRModule._SuppressOverloads)
                    {
                        var ctors = new ConstructorBinding(type, pyType, co.binder);
                        // ExtensionType types are untracked, so don't Incref() them.
                        // TODO: deprecate __overloads__ soon...
                        Runtime.PyDict_SetItem(dict, PyIdentifier.__overloads__, ctors.ObjectReference);
                        Runtime.PyDict_SetItem(dict, PyIdentifier.Overloads, ctors.ObjectReference);
                        ctors.DecrRefCount();
                    }

                    // don't generate the docstring if one was already set from a DocStringAttribute.
                    if (!CLRModule._SuppressDocs && doc.IsNull())
                    {
                        doc = co.GetDocString();
                        Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc);
                    }
                }
            }
            doc.Dispose();

            // The type has been modified after PyType_Ready has been called
            // Refresh the type
            Runtime.PyType_Modified(pyType.Reference);
        }
Пример #3
0
        private static ClassInfo GetClassInfo(Type type)
        {
            var         ci      = new ClassInfo();
            var         methods = new Hashtable();
            ArrayList   list;
            MethodInfo  meth;
            ManagedType ob;
            string      name;
            object      item;
            Type        tp;
            int         i, n;

            MemberInfo[] info  = type.GetMembers(BindingFlags);
            var          local = new Hashtable();
            var          items = new ArrayList();
            MemberInfo   m;

            // Loop through once to find out which names are declared
            for (i = 0; i < info.Length; i++)
            {
                m = info[i];
                if (m.DeclaringType == type)
                {
                    local[m.Name] = 1;
                }
            }

            // only [Flags] enums support bitwise operations
            if (type.IsEnum && type.IsFlagsEnum())
            {
                var opsImpl = typeof(EnumOps <>).MakeGenericType(type);
                foreach (var op in opsImpl.GetMethods(OpsHelper.BindingFlags))
                {
                    local[op.Name] = 1;
                }
                info = info.Concat(opsImpl.GetMethods(OpsHelper.BindingFlags)).ToArray();
            }

            // Now again to filter w/o losing overloaded member info
            for (i = 0; i < info.Length; i++)
            {
                m = info[i];
                if (local[m.Name] != null)
                {
                    items.Add(m);
                }
            }

            if (type.IsInterface)
            {
                // Interface inheritance seems to be a different animal:
                // more contractual, less structural.  Thus, a Type that
                // represents an interface that inherits from another
                // interface does not return the inherited interface's
                // methods in GetMembers. For example ICollection inherits
                // from IEnumerable, but ICollection's GetMemebers does not
                // return GetEnumerator.
                //
                // Not sure if this is the correct way to fix this, but it
                // seems to work. Thanks to Bruce Dodson for the fix.

                Type[] inheritedInterfaces = type.GetInterfaces();

                for (i = 0; i < inheritedInterfaces.Length; ++i)
                {
                    Type         inheritedType = inheritedInterfaces[i];
                    MemberInfo[] imembers      = inheritedType.GetMembers(BindingFlags);
                    for (n = 0; n < imembers.Length; n++)
                    {
                        m = imembers[n];
                        if (local[m.Name] == null)
                        {
                            items.Add(m);
                        }
                    }
                }

                // All interface implementations inherit from Object,
                // but GetMembers don't return them either.
                var objFlags = BindingFlags.Public | BindingFlags.Instance;
                foreach (var mi in typeof(object).GetMembers(objFlags))
                {
                    if (local[mi.Name] == null)
                    {
                        items.Add(mi);
                    }
                }
            }

            for (i = 0; i < items.Count; i++)
            {
                var mi = (MemberInfo)items[i];

                switch (mi.MemberType)
                {
                case MemberTypes.Method:
                    meth = (MethodInfo)mi;
                    if (!ShouldBindMethod(meth))
                    {
                        continue;
                    }
                    name = meth.Name;
                    item = methods[name];
                    if (item == null)
                    {
                        item = methods[name] = new ArrayList();
                    }
                    list = (ArrayList)item;
                    list.Add(meth);
                    continue;

                case MemberTypes.Property:
                    var pi = (PropertyInfo)mi;

                    if (!ShouldBindProperty(pi))
                    {
                        continue;
                    }

                    // Check for indexer
                    ParameterInfo[] args = pi.GetIndexParameters();
                    if (args.GetLength(0) > 0)
                    {
                        Indexer idx = ci.indexer;
                        if (idx == null)
                        {
                            ci.indexer = new Indexer();
                            idx        = ci.indexer;
                        }
                        idx.AddProperty(pi);
                        continue;
                    }

                    ob = new PropertyObject(pi);
                    ci.members[pi.Name] = ob;
                    continue;

                case MemberTypes.Field:
                    var fi = (FieldInfo)mi;
                    if (!ShouldBindField(fi))
                    {
                        continue;
                    }
                    ob = new FieldObject(fi);
                    ci.members[mi.Name] = ob;
                    continue;

                case MemberTypes.Event:
                    var ei = (EventInfo)mi;
                    if (!ShouldBindEvent(ei))
                    {
                        continue;
                    }
                    ob = new EventObject(ei);
                    ci.members[ei.Name] = ob;
                    continue;

                case MemberTypes.NestedType:
                    tp = (Type)mi;
                    if (!(tp.IsNestedPublic || tp.IsNestedFamily ||
                          tp.IsNestedFamORAssem))
                    {
                        continue;
                    }
                    // Note the given instance might be uninitialized
                    ob = GetClass(tp);
                    // GetClass returns a Borrowed ref. ci.members owns the reference.
                    ob.IncrRefCount();
                    ci.members[mi.Name] = ob;
                    continue;
                }
            }

            IDictionaryEnumerator iter = methods.GetEnumerator();

            while (iter.MoveNext())
            {
                name = (string)iter.Key;
                list = (ArrayList)iter.Value;

                var mlist = (MethodInfo[])list.ToArray(typeof(MethodInfo));

                ob = new MethodObject(type, name, mlist);
                ci.members[name] = ob;
                if (mlist.Any(OperatorMethod.IsOperatorMethod))
                {
                    string pyName        = OperatorMethod.GetPyMethodName(name);
                    string pyNameReverse = OperatorMethod.ReversePyMethodName(pyName);
                    OperatorMethod.FilterMethods(mlist, out var forwardMethods, out var reverseMethods);
                    // Only methods where the left operand is the declaring type.
                    if (forwardMethods.Length > 0)
                    {
                        ci.members[pyName] = new MethodObject(type, name, forwardMethods);
                    }
                    // Only methods where only the right operand is the declaring type.
                    if (reverseMethods.Length > 0)
                    {
                        ci.members[pyNameReverse] = new MethodObject(type, name, reverseMethods);
                    }
                }
            }

            if (ci.indexer == null && type.IsClass)
            {
                // Indexer may be inherited.
                var parent = type.BaseType;
                while (parent != null && ci.indexer == null)
                {
                    foreach (var prop in parent.GetProperties())
                    {
                        var args = prop.GetIndexParameters();
                        if (args.GetLength(0) > 0)
                        {
                            ci.indexer = new Indexer();
                            ci.indexer.AddProperty(prop);
                            break;
                        }
                    }
                    parent = parent.BaseType;
                }
            }

            return(ci);
        }
Пример #4
0
        private static ClassInfo GetClassInfo(Type type)
        {
            var         ci      = new ClassInfo(type);
            var         methods = new Hashtable();
            ArrayList   list;
            MethodInfo  meth;
            ManagedType ob;
            string      name;
            object      item;
            Type        tp;
            int         i, n;

            // This is complicated because inheritance in Python is name
            // based. We can't just find DeclaredOnly members, because we
            // could have a base class A that defines two overloads of a
            // method and a class B that defines two more. The name-based
            // descriptor Python will find needs to know about inherited
            // overloads as well as those declared on the sub class.
            BindingFlags flags = BindingFlags.Static |
                                 BindingFlags.Instance |
                                 BindingFlags.Public |
                                 BindingFlags.NonPublic;

            MemberInfo[] info  = type.GetMembers(flags);
            var          local = new Hashtable();
            var          items = new ArrayList();
            MemberInfo   m;

            // Loop through once to find out which names are declared
            for (i = 0; i < info.Length; i++)
            {
                m = info[i];
                if (m.DeclaringType == type)
                {
                    local[m.Name] = 1;
                }
            }

            // Now again to filter w/o losing overloaded member info
            for (i = 0; i < info.Length; i++)
            {
                m = info[i];
                if (local[m.Name] != null)
                {
                    items.Add(m);
                }
            }

            if (type.IsInterface)
            {
                // Interface inheritance seems to be a different animal:
                // more contractual, less structural.  Thus, a Type that
                // represents an interface that inherits from another
                // interface does not return the inherited interface's
                // methods in GetMembers. For example ICollection inherits
                // from IEnumerable, but ICollection's GetMemebers does not
                // return GetEnumerator.
                //
                // Not sure if this is the correct way to fix this, but it
                // seems to work. Thanks to Bruce Dodson for the fix.

                Type[] inheritedInterfaces = type.GetInterfaces();

                for (i = 0; i < inheritedInterfaces.Length; ++i)
                {
                    Type         inheritedType = inheritedInterfaces[i];
                    MemberInfo[] imembers      = inheritedType.GetMembers(flags);
                    for (n = 0; n < imembers.Length; n++)
                    {
                        m = imembers[n];
                        if (local[m.Name] == null)
                        {
                            items.Add(m);
                        }
                    }
                }
            }

            for (i = 0; i < items.Count; i++)
            {
                var mi = (MemberInfo)items[i];

                switch (mi.MemberType)
                {
                case MemberTypes.Method:
                    meth = (MethodInfo)mi;
                    if (!(meth.IsPublic || meth.IsFamily ||
                          meth.IsFamilyOrAssembly))
                    {
                        continue;
                    }
                    name = meth.Name;
                    item = methods[name];
                    if (item == null)
                    {
                        item = methods[name] = new ArrayList();
                    }
                    list = (ArrayList)item;
                    list.Add(meth);
                    continue;

                case MemberTypes.Property:
                    var pi = (PropertyInfo)mi;

                    MethodInfo mm = null;
                    try
                    {
                        mm = pi.GetGetMethod(true);
                        if (mm == null)
                        {
                            mm = pi.GetSetMethod(true);
                        }
                    }
                    catch (SecurityException)
                    {
                        // GetGetMethod may try to get a method protected by
                        // StrongNameIdentityPermission - effectively private.
                        continue;
                    }

                    if (mm == null)
                    {
                        continue;
                    }

                    if (!(mm.IsPublic || mm.IsFamily || mm.IsFamilyOrAssembly))
                    {
                        continue;
                    }

                    // Check for indexer
                    ParameterInfo[] args = pi.GetIndexParameters();
                    if (args.GetLength(0) > 0)
                    {
                        Indexer idx = ci.indexer;
                        if (idx == null)
                        {
                            ci.indexer = new Indexer();
                            idx        = ci.indexer;
                        }
                        idx.AddProperty(pi);
                        continue;
                    }

                    ob = new PropertyObject(pi);
                    ci.members[pi.Name] = ob;
                    continue;

                case MemberTypes.Field:
                    var fi = (FieldInfo)mi;
                    if (!(fi.IsPublic || fi.IsFamily || fi.IsFamilyOrAssembly))
                    {
                        continue;
                    }
                    ob = new FieldObject(fi);
                    ci.members[mi.Name] = ob;
                    continue;

                case MemberTypes.Event:
                    var        ei = (EventInfo)mi;
                    MethodInfo me = ei.GetAddMethod(true);
                    if (!(me.IsPublic || me.IsFamily || me.IsFamilyOrAssembly))
                    {
                        continue;
                    }
                    ob = new EventObject(ei);
                    ci.members[ei.Name] = ob;
                    continue;

                case MemberTypes.NestedType:
                    tp = (Type)mi;
                    if (!(tp.IsNestedPublic || tp.IsNestedFamily ||
                          tp.IsNestedFamORAssem))
                    {
                        continue;
                    }
                    // Note the given instance might be uninitialized
                    ob = GetClass(tp);
                    ci.members[mi.Name] = ob;
                    continue;
                }
            }

            IDictionaryEnumerator iter = methods.GetEnumerator();

            while (iter.MoveNext())
            {
                name = (string)iter.Key;
                list = (ArrayList)iter.Value;

                var mlist = (MethodInfo[])list.ToArray(typeof(MethodInfo));

                ob = new MethodObject(type, name, mlist);
                ci.members[name] = ob;
            }

            return(ci);
        }
Пример #5
0
        private static void InitClassBase(Type type, ClassBase impl)
        {
            // First, we introspect the managed type and build some class
            // information, including generating the member descriptors
            // that we'll be putting in the Python class __dict__.

            ClassInfo info = GetClassInfo(type);

            impl.indexer = info.indexer;

            // Now we allocate the Python type object to reflect the given
            // managed type, filling the Python type slots with thunks that
            // point to the managed methods providing the implementation.


            IntPtr tp = TypeManager.GetTypeHandle(impl, type);

            impl.tpHandle = tp;

            // Finally, initialize the class __dict__ and return the object.
            IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict);


            IDictionaryEnumerator iter = info.members.GetEnumerator();

            while (iter.MoveNext())
            {
                var item = (ManagedType)iter.Value;
                var name = (string)iter.Key;
                Runtime.PyDict_SetItemString(dict, name, item.pyHandle);
                // info.members are already useless
                Runtime.Py_DecRef(item.pyHandle);
            }

            // If class has constructors, generate an __doc__ attribute.
            IntPtr doc    = IntPtr.Zero;
            Type   marker = typeof(DocStringAttribute);
            var    attrs  = (Attribute[])type.GetCustomAttributes(marker, false);

            if (attrs.Length == 0)
            {
                doc = IntPtr.Zero;
            }
            else
            {
                var    attr   = (DocStringAttribute)attrs[0];
                string docStr = attr.DocString;
                doc = Runtime.PyString_FromString(docStr);
                Runtime.PyDict_SetItemString(dict, "__doc__", doc);
                Runtime.XDecref(doc);
            }

            var co = impl as ClassObject;

            // If this is a ClassObject AND it has constructors, generate a __doc__ attribute.
            // required that the ClassObject.ctors be changed to internal
            if (co != null)
            {
                if (co.ctors.Length > 0)
                {
                    // Implement Overloads on the class object
                    if (!CLRModule._SuppressOverloads)
                    {
                        var ctors = new ConstructorBinding(type, tp, co.binder);
                        // ExtensionType types are untracked, so don't Incref() them.
                        // TODO: deprecate __overloads__ soon...
                        Runtime.PyDict_SetItemString(dict, "__overloads__", ctors.pyHandle);
                        Runtime.PyDict_SetItemString(dict, "Overloads", ctors.pyHandle);
                        Runtime.Py_DecRef(ctors.pyHandle);
                    }

                    // don't generate the docstring if one was already set from a DocStringAttribute.
                    if (!CLRModule._SuppressDocs && doc == IntPtr.Zero)
                    {
                        doc = co.GetDocString();
                        Runtime.PyDict_SetItemString(dict, "__doc__", doc);
                        Runtime.XDecref(doc);
                    }
                }
            }
        }
Пример #6
0
        //====================================================================
        // Create a new ClassBase-derived instance that implements a reflected
        // managed type. The new object will be associated with a generated
        // Python type object.
        //====================================================================

        private static ClassBase CreateClass(Type type)
        {
            // First, we introspect the managed type and build some class
            // information, including generating the member descriptors
            // that we'll be putting in the Python class __dict__.

            ClassInfo info = GetClassInfo(type);

            // Next, select the appropriate managed implementation class.
            // Different kinds of types, such as array types or interface
            // types, want to vary certain implementation details to make
            // sure that the type semantics are consistent in Python.

            ClassBase impl;

            // Check to see if the given type extends System.Exception. This
            // lets us check once (vs. on every lookup) in case we need to
            // wrap Exception-derived types in old-style classes

            if (type.ContainsGenericParameters)
            {
                impl = new GenericType(type);
            }

            else if (type.IsSubclassOf(dtype))
            {
                impl = new DelegateObject(type);
            }

            else if (type.IsArray)
            {
                impl = new ArrayObject(type);
            }

            else if (type.IsInterface)
            {
                impl = new InterfaceObject(type);
            }

            else if (type == typeof(Exception) ||
                     type.IsSubclassOf(typeof(Exception)))
            {
                impl = new ExceptionClassObject(type);
            }

            else if (null != type.GetField("__pyobj__"))
            {
                impl = new ClassDerivedObject(type);
            }

            else
            {
                impl = new ClassObject(type);
            }

            impl.indexer = info.indexer;

            // Now we allocate the Python type object to reflect the given
            // managed type, filling the Python type slots with thunks that
            // point to the managed methods providing the implementation.


            IntPtr tp = TypeManager.GetTypeHandle(impl, type);

            impl.tpHandle = tp;

            // Finally, initialize the class __dict__ and return the object.
            IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict);


            IDictionaryEnumerator iter = info.members.GetEnumerator();

            while (iter.MoveNext())
            {
                ManagedType item = (ManagedType)iter.Value;
                string      name = (string)iter.Key;
                Runtime.PyDict_SetItemString(dict, name, item.pyHandle);
            }

            // If class has constructors, generate an __doc__ attribute.

            IntPtr doc;
            Type   marker = typeof(DocStringAttribute);

            Attribute[] attrs = (Attribute[])type.GetCustomAttributes(marker, false);
            if (attrs.Length == 0)
            {
                doc = IntPtr.Zero;
            }
            else
            {
                DocStringAttribute attr   = (DocStringAttribute)attrs[0];
                string             docStr = attr.DocString;
                doc = Runtime.PyString_FromString(docStr);
                Runtime.PyDict_SetItemString(dict, "__doc__", doc);
                Runtime.Decref(doc);
            }

            ClassObject co = impl as ClassObject;

            // If this is a ClassObject AND it has constructors, generate a __doc__ attribute.
            // required that the ClassObject.ctors be changed to internal
            if (co != null)
            {
                if (co.ctors.Length > 0)
                {
                    // Implement Overloads on the class object
                    if (!CLRModule._SuppressOverloads)
                    {
                        ConstructorBinding ctors = new ConstructorBinding(type, tp, co.binder);
                        // ExtensionType types are untracked, so don't Incref() them.
                        // XXX deprecate __overloads__ soon...
                        Runtime.PyDict_SetItemString(dict, "__overloads__", ctors.pyHandle);
                        Runtime.PyDict_SetItemString(dict, "Overloads", ctors.pyHandle);
                    }
                    if (!CLRModule._SuppressDocs)
                    {
                        doc = co.GetDocString();
                        Runtime.PyDict_SetItemString(dict, "__doc__", doc);
                        Runtime.Decref(doc);
                    }
                }
            }

            return(impl);
        }
Пример #7
0
        //====================================================================
        // Create a new ClassBase-derived instance that implements a reflected
        // managed type. The new object will be associated with a generated
        // Python type object.
        //====================================================================

        private static ClassBase CreateClass(Type type)
        {
            // First, we introspect the managed type and build some class
            // information, including generating the member descriptors
            // that we'll be putting in the Python class __dict__.

            ClassInfo info = GetClassInfo(type);

            // Next, select the appropriate managed implementation class.
            // Different kinds of types, such as array types or interface
            // types, want to vary certain implementation details to make
            // sure that the type semantics are consistent in Python.

            ClassBase impl;

            // Check to see if the given type extends System.Exception. This
            // lets us check once (vs. on every lookup) in case we need to
            // wrap Exception-derived types in old-style classes

            if (type.IsSubclassOf(dtype))
            {
                impl = new DelegateObject(type);
            }

            else if (type.IsArray)
            {
                impl = new ArrayObject(type);
            }

            else if (type.IsInterface)
            {
                impl = new InterfaceObject(type);
            }

            else
            {
                impl = new ClassObject(type);
                if (type == typeof(Exception) || type.IsSubclassOf(typeof(Exception)))
                {
                    impl.is_exception = true;
                }
            }

            impl.indexer = info.indexer;

            // Now we allocate the Python type object to reflect the given
            // managed type, filling the Python type slots with thunks that
            // point to the managed methods providing the implementation.


            IntPtr tp = TypeManager.GetTypeHandle(impl, type);

            impl.tpHandle = tp;

            // Finally, initialize the class __dict__ and return the object.
            IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict);


            IDictionaryEnumerator iter = info.members.GetEnumerator();

            while (iter.MoveNext())
            {
                ManagedType item = (ManagedType)iter.Value;
                string      name = (string)iter.Key;
                Runtime.PyDict_SetItemString(dict, name, item.pyHandle);
            }

            // If class has constructors, generate an __doc__ attribute.

            ClassObject co = impl as ClassObject;

            if (co != null)
            {
                IntPtr doc = co.GetDocString();
                Runtime.PyDict_SetItemString(dict, "__doc__", doc);
                Runtime.Decref(doc);
            }

            return(impl);
        }
Пример #8
0
        private static void InitClassBase(Type type, ClassBase impl)
        {
            // First, we introspect the managed type and build some class
            // information, including generating the member descriptors
            // that we'll be putting in the Python class __dict__.

            ClassInfo info = GetClassInfo(type);

            impl.indexer     = info.indexer;
            impl.richcompare = new Dictionary <int, MethodObject>();

            // Now we allocate the Python type object to reflect the given
            // managed type, filling the Python type slots with thunks that
            // point to the managed methods providing the implementation.


            IntPtr tp = TypeManager.GetTypeHandle(impl, type);

            // Finally, initialize the class __dict__ and return the object.
            IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict);


            if (impl.dotNetMembers == null)
            {
                impl.dotNetMembers = new List <string>();
            }
            IDictionaryEnumerator iter = info.members.GetEnumerator();

            while (iter.MoveNext())
            {
                var item = (ManagedType)iter.Value;
                var name = (string)iter.Key;
                impl.dotNetMembers.Add(name);
                Runtime.PyDict_SetItemString(dict, name, item.pyHandle);
                // Decref the item now that it's been used.
                item.DecrRefCount();
                if (ClassBase.CilToPyOpMap.TryGetValue(name, out var pyOp))
                {
                    impl.richcompare.Add(pyOp, (MethodObject)item);
                }
            }

            // If class has constructors, generate an __doc__ attribute.
            IntPtr doc    = IntPtr.Zero;
            Type   marker = typeof(DocStringAttribute);
            var    attrs  = (Attribute[])type.GetCustomAttributes(marker, false);

            if (attrs.Length == 0)
            {
                doc = IntPtr.Zero;
            }
            else
            {
                var    attr   = (DocStringAttribute)attrs[0];
                string docStr = attr.DocString;
                doc = Runtime.PyString_FromString(docStr);
                Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc);
                Runtime.XDecref(doc);
            }

            var co = impl as ClassObject;

            // If this is a ClassObject AND it has constructors, generate a __doc__ attribute.
            // required that the ClassObject.ctors be changed to internal
            if (co != null)
            {
                if (co.NumCtors > 0)
                {
                    // Implement Overloads on the class object
                    if (!CLRModule._SuppressOverloads)
                    {
                        var ctors = new ConstructorBinding(type, tp, co.binder);
                        // ExtensionType types are untracked, so don't Incref() them.
                        // TODO: deprecate __overloads__ soon...
                        Runtime.PyDict_SetItem(dict, PyIdentifier.__overloads__, ctors.pyHandle);
                        Runtime.PyDict_SetItem(dict, PyIdentifier.Overloads, ctors.pyHandle);
                        ctors.DecrRefCount();
                    }

                    // don't generate the docstring if one was already set from a DocStringAttribute.
                    if (!CLRModule._SuppressDocs && doc == IntPtr.Zero)
                    {
                        doc = co.GetDocString();
                        Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc);
                        Runtime.XDecref(doc);
                    }
                }
            }
            // The type has been modified after PyType_Ready has been called
            // Refresh the type
            Runtime.PyType_Modified(tp);
        }