//==================================================================== // Implements __setitem__ for reflected classes and value types. //==================================================================== public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) { //ManagedType self = GetManagedObject(ob); IntPtr tp = Runtime.PyObject_TYPE(ob); ClassBase cls = (ClassBase)GetManagedObject(tp); if (cls.indexer == null || !cls.indexer.CanSet) { Exceptions.SetError(Exceptions.TypeError, "object doesn't support item assignment" ); return(-1); } // Arg may be a tuple in the case of an indexer with multiple // parameters. If so, use it directly, else make a new tuple // with the index arg (method binders expect arg tuples). IntPtr args = idx; bool free = false; if (!Runtime.PyTuple_Check(idx)) { args = Runtime.PyTuple_New(1); Runtime.Incref(idx); Runtime.PyTuple_SetItem(args, 0, idx); free = true; } int i = Runtime.PyTuple_Size(args); IntPtr real = Runtime.PyTuple_New(i + 1); for (int n = 0; n < i; n++) { IntPtr item = Runtime.PyTuple_GetItem(args, n); Runtime.Incref(item); Runtime.PyTuple_SetItem(real, n, item); } Runtime.Incref(v); Runtime.PyTuple_SetItem(real, i, v); try { cls.indexer.SetItem(ob, real); } finally { Runtime.Decref(real); if (free) { Runtime.Decref(args); } } if (Exceptions.ErrorOccurred()) { return(-1); } return(0); }
//==================================================================== // Implementation of [] semantics for reflected types. This mainly // exists to implement the Array[int] syntax for creating arrays. //==================================================================== public override IntPtr type_subscript(IntPtr ob, IntPtr idx) { if ((this.type) != typeof(Array)) { return(Exceptions.RaiseTypeError("unsubscriptable object")); } if (Runtime.PyTuple_Check(idx)) { return(Exceptions.RaiseTypeError("expected single type")); } ClassBase c = GetManagedObject(idx) as ClassBase; Type t = (c != null) ? c.type : Converter.GetTypeByAlias(idx); if (t == null) { return(Exceptions.RaiseTypeError("type expected")); } Array a = Array.CreateInstance(t, 0); c = ClassManager.GetClass(a.GetType()); Runtime.Incref(c.pyHandle); return(c.pyHandle); }
// Called from Converter.ToPython for types that are python subclasses of managed types. // The referenced python object is returned instead of a new wrapper. internal static IntPtr ToPython(IPythonDerivedType obj) { // derived types have a __pyobj__ field that gets set to the python // object in the overriden constructor FieldInfo fi = obj.GetType().GetField("__pyobj__"); CLRObject self = (CLRObject)fi.GetValue(obj); Runtime.Incref(self.pyHandle); // when the C# constructor creates the python object it starts as a weak // reference with a reference count of 0. Now we're passing this object // to Python the reference count needs to be incremented and the reference // needs to be replaced with a strong reference to stop the C# object being // collected while Python still has a reference to it. if (Runtime.Refcount(self.pyHandle) == 1) { GCHandle gc = GCHandle.Alloc(self, GCHandleType.Normal); Marshal.WriteIntPtr(self.pyHandle, ObjectOffset.magic(self.tpHandle), (IntPtr)gc); self.gcHandle.Free(); self.gcHandle = gc; // now the object has a python reference it's safe for the python GC to track it Runtime.PyObject_GC_Track(self.pyHandle); } return(self.pyHandle); }
//=================================================================== // Preloads all currently-known names for the module namespace. This // can be called multiple times, to add names from assemblies that // may have been loaded since the last call to the method. //=================================================================== public void LoadNames() { ManagedType m = null; foreach (string name in AssemblyManager.GetNames(_namespace)) { this.cache.TryGetValue(name, out m); if (m == null) { ManagedType attr = this.GetAttribute(name, true); if (Runtime.wrap_exceptions) { if (attr is ExceptionClassObject) { ExceptionClassObject c = attr as ExceptionClassObject; if (c != null) { IntPtr p = attr.pyHandle; IntPtr r = Exceptions.GetExceptionClassWrapper(p); Runtime.PyDict_SetItemString(dict, name, r); Runtime.Incref(r); } } } } } }
//==================================================================== // MethodBinding __getattribute__ implementation. //==================================================================== public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { MethodBinding self = (MethodBinding)GetManagedObject(ob); if (!Runtime.PyString_Check(key)) { Exceptions.SetError(Exceptions.TypeError, "string expected"); return(IntPtr.Zero); } string name = Runtime.GetManagedString(key); if (name == "__doc__") { IntPtr doc = self.m.GetDocString(); Runtime.Incref(doc); return(doc); } if (name == "__overloads__") { OverloadMapper om = new OverloadMapper(self.m, self.target); Runtime.Incref(om.pyHandle); return(om.pyHandle); } return(Runtime.PyObject_GenericGetAttr(ob, key)); }
public PythonException() : base() { Runtime.PyErr_Fetch(ref excType, ref excValue, ref excTb); Runtime.Incref(excType); Runtime.Incref(excValue); Runtime.Incref(excTb); }
//==================================================================== // helper methods for raising warnings //==================================================================== /// <summary> /// Alias for Python's warnings.warn() function. /// </summary> public static void warn(string message, IntPtr exception, int stacklevel) { if ((exception == IntPtr.Zero) || (Runtime.PyObject_IsSubclass(exception, Exceptions.Warning) != 1)) { Exceptions.RaiseTypeError("Invalid exception"); } Runtime.Incref(warnings_module); IntPtr warn = Runtime.PyObject_GetAttrString(warnings_module, "warn"); Runtime.Decref(warnings_module); Exceptions.ErrorCheck(warn); IntPtr args = Runtime.PyTuple_New(3); IntPtr msg = Runtime.PyString_FromString(message); Runtime.Incref(exception); // PyTuple_SetItem steals a reference IntPtr level = Runtime.PyInt_FromInt32(stacklevel); Runtime.PyTuple_SetItem(args, 0, msg); Runtime.PyTuple_SetItem(args, 1, exception); Runtime.PyTuple_SetItem(args, 2, level); IntPtr result = Runtime.PyObject_CallObject(warn, args); Exceptions.ErrorCheck(result); Runtime.Decref(warn); Runtime.Decref(result); Runtime.Decref(args); }
//==================================================================== // Implement explicit overload selection using subscript syntax ([]). //==================================================================== public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) { OverloadMapper self = (OverloadMapper)GetManagedObject(tp); // Note: if the type provides a non-generic method with N args // and a generic method that takes N params, then we always // prefer the non-generic version in doing overload selection. Type[] types = Runtime.PythonArgsToTypeArray(idx); if (types == null) { return(Exceptions.RaiseTypeError("type(s) expected")); } MethodInfo mi = MethodBinder.MatchSignature(self.m.info, types); if (mi == null) { string e = "No match found for signature"; return(Exceptions.RaiseTypeError(e)); } MethodBinding mb = new MethodBinding(self.m, self.target); mb.info = mi; Runtime.Incref(mb.pyHandle); return(mb.pyHandle); }
//==================================================================== // ConstructorBinding __repr__ implementation [borrowed from MethodObject]. //==================================================================== public static IntPtr tp_repr(IntPtr ob) { ConstructorBinding self = (ConstructorBinding)GetManagedObject(ob); if (self.repr != IntPtr.Zero) { Runtime.Incref(self.repr); return(self.repr); } MethodBase[] methods = self.ctorBinder.GetMethods(); string name = self.type.FullName; string doc = ""; for (int i = 0; i < methods.Length; i++) { if (doc.Length > 0) { doc += "\n"; } string str = methods[i].ToString(); int idx = str.IndexOf("("); doc += String.Format("{0}{1}", name, str.Substring(idx)); } self.repr = Runtime.PyString_FromString(doc); Runtime.Incref(self.repr); return(self.repr); }
//==================================================================== // Descriptor __get__ implementation. A getattr on an event returns // a "bound" event that keeps a reference to the object instance. //==================================================================== public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) { EventObject self = GetManagedObject(ds) as EventObject; EventBinding binding; if (self == null) { return(Exceptions.RaiseTypeError("invalid argument")); } // If the event is accessed through its type (rather than via // an instance) we return an 'unbound' EventBinding that will // be cached for future accesses through the type. if (ob == IntPtr.Zero) { if (self.unbound == null) { self.unbound = new EventBinding(self, IntPtr.Zero); } binding = self.unbound; Runtime.Incref(binding.pyHandle); return(binding.pyHandle); } if (Runtime.PyObject_IsInstance(ob, tp) < 1) { return(Exceptions.RaiseTypeError("invalid argument")); } binding = new EventBinding(self, ob); return(binding.pyHandle); }
//==================================================================== // Implements __cmp__ for reflected delegate types. //==================================================================== #if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) public static new IntPtr tp_richcompare(IntPtr ob, IntPtr other, int op) { if (op != Runtime.Py_EQ && op != Runtime.Py_NE) { Runtime.Incref(Runtime.PyNotImplemented); return(Runtime.PyNotImplemented); } IntPtr pytrue = Runtime.PyTrue; IntPtr pyfalse = Runtime.PyFalse; // swap true and false for NE if (op != Runtime.Py_EQ) { pytrue = Runtime.PyFalse; pyfalse = Runtime.PyTrue; } Delegate d1 = GetTrueDelegate(ob); Delegate d2 = GetTrueDelegate(other); if (d1 == d2) { Runtime.Incref(pytrue); return(pytrue); } Runtime.Incref(pyfalse); return(pyfalse); }
public MethodBinding(MethodObject m, IntPtr target) : base() { Runtime.Incref(target); this.target = target; this.info = null; this.m = m; }
public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) { MethodBinding self = (MethodBinding)GetManagedObject(ob); // This supports calling a method 'unbound', passing the instance // as the first argument. Note that this is not supported if any // of the overloads are static since we can't know if the intent // was to call the static method or the unbound instance method. if ((self.target == IntPtr.Zero) && (!self.m.IsStatic())) { if (Runtime.PyTuple_Size(args) < 1) { Exceptions.SetError(Exceptions.TypeError, "not enough arguments" ); return(IntPtr.Zero); } int len = Runtime.PyTuple_Size(args); IntPtr uargs = Runtime.PyTuple_GetSlice(args, 1, len); IntPtr inst = Runtime.PyTuple_GetItem(args, 0); Runtime.Incref(inst); IntPtr r = self.m.Invoke(inst, uargs, kw, self.info); Runtime.Decref(inst); Runtime.Decref(uargs); return(r); } return(self.m.Invoke(self.target, args, kw, self.info)); }
public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, string origMethodName, Object[] args) { FieldInfo fi = obj.GetType().GetField("__pyobj__"); CLRObject self = (CLRObject)fi.GetValue(obj); if (null != self) { List <PyObject> disposeList = new List <PyObject>(); IntPtr gs = Runtime.PyGILState_Ensure(); try { Runtime.Incref(self.pyHandle); PyObject pyself = new PyObject(self.pyHandle); disposeList.Add(pyself); Runtime.Incref(Runtime.PyNone); PyObject pynone = new PyObject(Runtime.PyNone); disposeList.Add(pynone); PyObject method = pyself.GetAttr(methodName, pynone); disposeList.Add(method); if (method.Handle != Runtime.PyNone) { // if the method hasn't been overriden then it will be a managed object ManagedType managedMethod = ManagedType.GetManagedObject(method.Handle); if (null == managedMethod) { PyObject[] pyargs = new PyObject[args.Length]; for (int i = 0; i < args.Length; ++i) { pyargs[i] = new PyObject(Converter.ToPython(args[i], args[i].GetType())); disposeList.Add(pyargs[i]); } PyObject py_result = method.Invoke(pyargs); disposeList.Add(py_result); return; } } } finally { foreach (PyObject x in disposeList) { if (x != null) { x.Dispose(); } } Runtime.PyGILState_Release(gs); } } obj.GetType().InvokeMember(origMethodName, BindingFlags.InvokeMethod, null, obj, args); }
//==================================================================== // OverloadMapper __repr__ implementation. //==================================================================== public static IntPtr tp_repr(IntPtr op) { OverloadMapper self = (OverloadMapper)GetManagedObject(op); IntPtr doc = self.m.GetDocString(); Runtime.Incref(doc); return(doc); }
public ConstructorBinding(Type type, IntPtr pyTypeHndl, ConstructorBinder ctorBinder) : base() { this.type = type; Runtime.Incref(pyTypeHndl); this.pyTypeHndl = pyTypeHndl; this.ctorBinder = ctorBinder; repr = IntPtr.Zero; }
//=================================================================== // Return the clr python module (new reference) //=================================================================== public static IntPtr GetCLRModule(IntPtr?fromList = null) { root.InitializePreload(); #if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) // update the module dictionary with the contents of the root dictionary root.LoadNames(); IntPtr py_mod_dict = Runtime.PyModule_GetDict(py_clr_module); IntPtr clr_dict = Runtime._PyObject_GetDictPtr(root.pyHandle); // PyObject** clr_dict = (IntPtr)Marshal.PtrToStructure(clr_dict, typeof(IntPtr)); Runtime.PyDict_Update(py_mod_dict, clr_dict); // find any items from the fromlist and get them from the root if they're not // aleady in the module dictionary if (fromList != null && fromList != IntPtr.Zero) { if (Runtime.PyTuple_Check(fromList.GetValueOrDefault())) { Runtime.Incref(py_mod_dict); using (PyDict mod_dict = new PyDict(py_mod_dict)) { Runtime.Incref(fromList.GetValueOrDefault()); using (PyTuple from = new PyTuple(fromList.GetValueOrDefault())) { foreach (PyObject item in from) { if (mod_dict.HasKey(item)) { continue; } string s = item.AsManagedObject(typeof(string)) as string; if (null == s) { continue; } ManagedType attr = root.GetAttribute(s, true); if (null == attr) { continue; } Runtime.Incref(attr.pyHandle); using (PyObject obj = new PyObject(attr.pyHandle)) { mod_dict.SetItem(s, obj); } } } } } } Runtime.Incref(py_clr_module); return(py_clr_module); #else Runtime.Incref(root.pyHandle); return(root.pyHandle); #endif }
//==================================================================== // ModuleObject __getattribute__ implementation. Module attributes // are always either classes or sub-modules representing subordinate // namespaces. CLR modules implement a lazy pattern - the sub-modules // and classes are created when accessed and cached for future use. //==================================================================== public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { ModuleObject self = (ModuleObject)GetManagedObject(ob); if (!Runtime.PyString_Check(key)) { Exceptions.SetError(Exceptions.TypeError, "string expected"); return(IntPtr.Zero); } IntPtr op = Runtime.PyDict_GetItem(self.dict, key); if (op != IntPtr.Zero) { Runtime.Incref(op); return(op); } string name = Runtime.GetManagedString(key); if (name == "__dict__") { Runtime.Incref(self.dict); return(self.dict); } ManagedType attr = self.GetAttribute(name, true); if (attr == null) { Exceptions.SetError(Exceptions.AttributeError, name); return(IntPtr.Zero); } // XXX - hack required to recognize exception types. These types // may need to be wrapped in old-style class wrappers in versions // of Python where new-style classes cannot be used as exceptions. if (Runtime.wrap_exceptions) { if (attr is ExceptionClassObject) { ExceptionClassObject c = attr as ExceptionClassObject; if (c != null) { IntPtr p = attr.pyHandle; IntPtr r = Exceptions.GetExceptionClassWrapper(p); Runtime.PyDict_SetItemString(self.dict, name, r); Runtime.Incref(r); return(r); } } } Runtime.Incref(attr.pyHandle); return(attr.pyHandle); }
/// <summary> /// PyTuple Constructor /// </summary> /// /// <remarks> /// Copy constructor - obtain a PyTuple from a generic PyObject. An /// ArgumentException will be thrown if the given object is not a /// Python tuple object. /// </remarks> public PyTuple(PyObject o) : base() { if (!IsTupleType(o)) { throw new ArgumentException("object is not a tuple"); } Runtime.Incref(o.obj); obj = o.obj; }
/// <summary> /// PyString Constructor /// </summary> /// /// <remarks> /// Copy constructor - obtain a PyString from a generic PyObject. /// An ArgumentException will be thrown if the given object is not /// a Python string object. /// </remarks> public PyString(PyObject o) : base() { if (!IsStringType(o)) { throw new ArgumentException("object is not a string"); } Runtime.Incref(o.obj); obj = o.obj; }
/// <summary> /// PyDict Constructor /// </summary> /// /// <remarks> /// Copy constructor - obtain a PyDict from a generic PyObject. An /// ArgumentException will be thrown if the given object is not a /// Python dictionary object. /// </remarks> public PyDict(PyObject o) : base() { if (!IsDictType(o)) { throw new ArgumentException("object is not a dict"); } Runtime.Incref(o.obj); obj = o.obj; }
public BoundContructor(Type type, IntPtr pyTypeHndl, ConstructorBinder ctorBinder, ConstructorInfo ci) : base() { this.type = type; Runtime.Incref(pyTypeHndl); this.pyTypeHndl = pyTypeHndl; this.ctorBinder = ctorBinder; ctorInfo = ci; repr = IntPtr.Zero; }
internal static IntPtr CreateSubType(IntPtr args) { IntPtr py_name = Runtime.PyTuple_GetItem(args, 0); IntPtr bases = Runtime.PyTuple_GetItem(args, 1); IntPtr dict = Runtime.PyTuple_GetItem(args, 2); IntPtr base_ = Runtime.PyTuple_GetItem(bases, 0); string name = Runtime.GetManagedString(py_name); IntPtr type = AllocateTypeObject(name); Marshal.WriteIntPtr(type, TypeOffset.ob_type, Runtime.PyCLRMetaType); Runtime.Incref(Runtime.PyCLRMetaType); Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize); Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero); IntPtr offset = (IntPtr)ObjectOffset.ob_dict; Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset); IntPtr dc = Runtime.PyDict_Copy(dict); Marshal.WriteIntPtr(type, TypeOffset.tp_dict, dc); Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); Runtime.Incref(base_); int flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.BaseType; flags |= TypeFlags.Subclass; flags |= TypeFlags.HaveGC; Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags); CopySlot(base_, type, TypeOffset.tp_traverse); CopySlot(base_, type, TypeOffset.tp_clear); CopySlot(base_, type, TypeOffset.tp_is_gc); Runtime.PyType_Ready(type); IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); IntPtr mod = Runtime.PyString_FromString("CLR"); Runtime.PyDict_SetItemString(tp_dict, "__module__", mod); // for now, move up hidden handle... IntPtr gc = Marshal.ReadIntPtr(base_, TypeOffset.magic()); Marshal.WriteIntPtr(type, TypeOffset.magic(), gc); return(type); }
//=================================================================== // Return the clr python module (new reference) //=================================================================== public static IntPtr GetCLRModule() { root.InitializePreload(); #if (PYTHON32 || PYTHON33 || PYTHON34) Runtime.Incref(py_clr_module); return(py_clr_module); #else Runtime.Incref(root.pyHandle); return(root.pyHandle); #endif }
//==================================================================== // In a few situations, we don't have any advisory type information // when we want to convert an object to Python. //==================================================================== internal static IntPtr ToPythonImplicit(Object value) { if (value == null) { IntPtr result = Runtime.PyNone; Runtime.Incref(result); return(result); } return(ToPython(value, objectType)); }
/// <summary> /// FromManagedObject Method /// </summary> /// /// <remarks> /// Given an arbitrary managed object, return a Python instance that /// reflects the managed object. /// </remarks> public static PyObject FromManagedObject(object ob) { // Special case: if ob is null, we return None. if (ob == null) { Runtime.Incref(Runtime.PyNone); return(new PyObject(Runtime.PyNone)); } IntPtr op = CLRObject.GetInstHandle(ob); return(new PyObject(op)); }
//==================================================================== // Implements subscript syntax for reflected generic types. A closed // type is created by binding the generic type via subscript syntax: // inst = List[str]() //==================================================================== public override IntPtr type_subscript(IntPtr idx) { Type[] types = Runtime.PythonArgsToTypeArray(idx); if (types == null) { return(Exceptions.RaiseTypeError("type(s) expected")); } if (!this.type.IsGenericTypeDefinition) { return(Exceptions.RaiseTypeError( "type is not a generic type definition" )); } // This is a little tricky, because an instance of GenericType // may represent either a specific generic type, or act as an // alias for one or more generic types with the same base name. if (this.type.ContainsGenericParameters) { Type[] args = this.type.GetGenericArguments(); Type target = null; if (args.Length == types.Length) { target = this.type; } else { foreach (Type t in GenericUtil.GenericsForType(this.type)) { if (t.GetGenericArguments().Length == types.Length) { target = t; break; } } } if (target != null) { Type t = target.MakeGenericType(types); ManagedType c = (ManagedType)ClassManager.GetClass(t); Runtime.Incref(c.pyHandle); return(c.pyHandle); } return(Exceptions.RaiseTypeError("no type matches params")); } return(Exceptions.RaiseTypeError("unsubscriptable object")); }
public MethodBinding(MethodObject m, IntPtr target, IntPtr targetType) : base() { Runtime.Incref(target); this.target = target; Runtime.Incref(targetType); if (targetType == IntPtr.Zero) { targetType = Runtime.PyObject_Type(target); } this.targetType = targetType; this.info = null; this.m = m; }
//==================================================================== // MethodBinding __call__ implementation. //==================================================================== public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) { MethodBinding self = (MethodBinding)GetManagedObject(ob); // This works around a situation where the wrong generic method is picked, // for example this method in the tests: string Overloaded<T>(int arg1, int arg2, string arg3) if (self.info != null) { if (self.info.IsGenericMethod) { int len = Runtime.PyTuple_Size(args); Type[] sigTp = Runtime.PythonArgsToTypeArray(args, true); if (sigTp != null) { Type[] genericTp = self.info.GetGenericArguments(); MethodInfo betterMatch = MethodBinder.MatchSignatureAndParameters(self.m.info, genericTp, sigTp); if (betterMatch != null) { self.info = betterMatch; } } } } // This supports calling a method 'unbound', passing the instance // as the first argument. Note that this is not supported if any // of the overloads are static since we can't know if the intent // was to call the static method or the unbound instance method. if ((self.target == IntPtr.Zero) && (!self.m.IsStatic())) { int len = Runtime.PyTuple_Size(args); if (len < 1) { Exceptions.SetError(Exceptions.TypeError, "not enough arguments"); return(IntPtr.Zero); } IntPtr uargs = Runtime.PyTuple_GetSlice(args, 1, len); IntPtr inst = Runtime.PyTuple_GetItem(args, 0); Runtime.Incref(inst); IntPtr r = self.m.Invoke(inst, uargs, kw, self.info); Runtime.Decref(inst); Runtime.Decref(uargs); return(r); } return(self.m.Invoke(self.target, args, kw, self.info)); }
/// <summary> /// PyList Constructor /// </summary> /// /// <remarks> /// Creates a new Python list object from an array of PyObjects. /// </remarks> public PyList(PyObject[] items) : base() { int count = items.Length; obj = Runtime.PyList_New(count); for (int i = 0; i < count; i++) { IntPtr ptr = items[i].obj; Runtime.Incref(ptr); int r = Runtime.PyList_SetItem(obj, i, ptr); if (r < 0) { throw new PythonException(); } } }