X Tutup
using System; using System.Reflection; using System.Runtime.InteropServices; namespace Python.Runtime { /// /// Provides the implementation for reflected interface types. Managed /// interfaces are represented in Python by actual Python type objects. /// Each of those type objects is associated with an instance of this /// class, which provides the implementation for the Python type. /// [Serializable] internal class InterfaceObject : ClassBase { [NonSerialized] internal ConstructorInfo? ctor; internal InterfaceObject(Type tp) : base(tp) { this.ctor = TryGetCOMConstructor(tp); } static ConstructorInfo? TryGetCOMConstructor(Type tp) { var comClass = (CoClassAttribute?)Attribute.GetCustomAttribute(tp, cc_attr); return comClass?.CoClass.GetConstructor(Type.EmptyTypes); } private static readonly Type cc_attr; static InterfaceObject() { cc_attr = typeof(CoClassAttribute); } /// /// Implements __new__ for reflected interface types. /// public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, BorrowedReference kw) { var self = (InterfaceObject)GetManagedObject(tp)!; if (!self.type.Valid) { return Exceptions.RaiseTypeError(self.type.DeletedMessage); } var nargs = Runtime.PyTuple_Size(args); Type type = self.type.Value; object obj; if (nargs == 1) { BorrowedReference inst = Runtime.PyTuple_GetItem(args, 0); if (GetManagedObject(inst) is CLRObject co && type.IsInstanceOfType(co.inst)) { obj = co.inst; } else { Exceptions.SetError(Exceptions.TypeError, $"object does not implement {type.Name}"); return default; } } else if (nargs == 0 && self.ctor != null) { obj = self.ctor.Invoke(null); if (obj == null || !type.IsInstanceOfType(obj)) { Exceptions.SetError(Exceptions.TypeError, "CoClass default constructor failed"); return default; } } else { Exceptions.SetError(Exceptions.TypeError, "interface takes exactly one argument"); return default; } return self.TryWrapObject(obj); } /// /// Wrap the given object in an interface object, so that only methods /// of the interface are available. /// public NewReference TryWrapObject(object impl) => this.type.Valid ? CLRObject.GetReference(impl, ClassManager.GetClass(this.type.Value)) : Exceptions.RaiseTypeError(this.type.DeletedMessage); /// /// Expose the wrapped implementation through attributes in both /// converted/encoded (__implementation__) and raw (__raw_implementation__) form. /// public static NewReference tp_getattro(BorrowedReference ob, BorrowedReference key) { var clrObj = (CLRObject)GetManagedObject(ob)!; if (!Runtime.PyString_Check(key)) { return Exceptions.RaiseTypeError("string expected"); } string? name = Runtime.GetManagedString(key); if (name == "__implementation__") { return Converter.ToPython(clrObj.inst); } else if (name == "__raw_implementation__") { return CLRObject.GetReference(clrObj.inst); } return Runtime.PyObject_GenericGetAttr(ob, key); } protected override void OnDeserialization(object sender) { base.OnDeserialization(sender); if (this.type.Valid) { this.ctor = TryGetCOMConstructor(this.type.Value); } } } }
X Tutup