//==================================================================== // EventBinding dealloc implementation. //==================================================================== public static new void tp_dealloc(IntPtr ob) { EventBinding self = (EventBinding)GetManagedObject(ob); Runtime.Decref(self.target); ExtensionType.FinalizeObject(self); }
public static void tp_dealloc(IntPtr tp) { // Fix this when we dont cheat on the handle for subclasses! int flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags); if ((flags & TypeFlags.Subclass) == 0) { IntPtr gc = Marshal.ReadIntPtr(tp, TypeOffset.magic()); ((GCHandle)gc).Free(); } IntPtr op = Marshal.ReadIntPtr(tp, TypeOffset.ob_type); Runtime.Decref(op); // Delegate the rest of finalization the Python metatype. Note // that the PyType_Type implementation of tp_dealloc will call // tp_free on the type of the type being deallocated - in this // case our CLR metatype. That is why we implement tp_free. op = Marshal.ReadIntPtr(Runtime.PyTypeType, TypeOffset.tp_dealloc); NativeCall.Void_Call_1(op, tp); return; }
//==================================================================== // OverloadMapper dealloc implementation. //==================================================================== public static new void tp_dealloc(IntPtr ob) { OverloadMapper self = (OverloadMapper)GetManagedObject(ob); Runtime.Decref(self.target); ExtensionType.FinalizeObject(self); }
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)); }
//==================================================================== // 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); }
public static KeywordArguments kw(params object[] kv) { var dict = new KeywordArguments(); if (kv.Length % 2 != 0) { throw new ArgumentException("Must have an equal number of keys and values"); } for (int i = 0; i < kv.Length; i += 2) { IntPtr value; if (kv[i + 1] is PyObject) { value = ((PyObject)kv[i + 1]).Handle; } else { value = Converter.ToPython(kv[i + 1], kv[i + 1].GetType()); } if (Runtime.PyDict_SetItemString(dict.Handle, (string)kv[i], value) != 0) { throw new ArgumentException(string.Format("Cannot add key '{0}' to dictionary.", (string)kv[i])); } if (!(kv[i + 1] is PyObject)) { Runtime.Decref(value); } } return(dict); }
//==================================================================== // 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); }
public ModuleObject(string name) : base() { moduleName = (name == String.Empty) ? "CLR" : name; cache = new Hashtable(); _namespace = name; dict = Runtime.PyDict_New(); IntPtr pyname = Runtime.PyString_FromString(moduleName); Runtime.PyDict_SetItemString(dict, "__name__", pyname); Runtime.PyDict_SetItemString(dict, "__file__", Runtime.PyNone); Runtime.PyDict_SetItemString(dict, "__doc__", Runtime.PyNone); Runtime.Decref(pyname); Marshal.WriteIntPtr(this.pyHandle, ObjectOffset.ob_dict, dict); // This hackery is required in order to allow a plain Python to // import the managed runtime via the CLR bootstrapper module. // The standard Python machinery in control at the time of the // import requires the module to pass PyModule_Check. :( if (!hacked) { IntPtr type = this.tpHandle; IntPtr mro = Marshal.ReadIntPtr(type, TypeOffset.tp_mro); IntPtr ext = Runtime.ExtendTuple(mro, Runtime.PyModuleType); Marshal.WriteIntPtr(type, TypeOffset.tp_mro, ext); Runtime.Decref(mro); hacked = true; } }
internal static IntPtr GetExceptionInstanceWrapper(IntPtr real) { // Given the pointer to a new-style class instance representing a // managed exception, return an appropriate old-style class // wrapper instance that delegates to the wrapped instance. IntPtr tp = Runtime.PyObject_TYPE(real); if (Runtime.PyObject_TYPE(tp) == Runtime.PyInstanceType) { return(real); } // Get / generate a class wrapper, instantiate it and set its // _inner attribute to the real new-style exception instance. IntPtr ct = GetExceptionClassWrapper(tp); Exceptions.ErrorCheck(ct); IntPtr op = Runtime.PyInstance_NewRaw(ct, IntPtr.Zero); Exceptions.ErrorCheck(op); IntPtr d = Runtime.PyObject_GetAttrString(op, "__dict__"); Exceptions.ErrorCheck(d); Runtime.PyDict_SetItemString(d, "_inner", real); Runtime.Decref(d); return(op); }
/// <summary> /// SetError Method /// </summary> /// /// <remarks> /// Sets the current Python exception given a CLR exception /// object. The CLR exception instance is wrapped as a Python /// object, allowing it to be handled naturally from Python. /// </remarks> public static void SetError(Exception e) { // Because delegates allow arbitrary nestings of Python calling // managed calling Python calling... etc. it is possible that we // might get a managed exception raised that is a wrapper for a // Python exception. In that case we'd rather have the real thing. PythonException pe = e as PythonException; if (pe != null) { Runtime.PyErr_SetObject(pe.PyType, pe.PyValue); return; } IntPtr op = CLRObject.GetInstHandle(e); // XXX - hack to raise a compatible old-style exception ;( if (Runtime.wrap_exceptions) { op = GetExceptionInstanceWrapper(op); } IntPtr etype = Runtime.PyObject_GetAttrString(op, "__class__"); Runtime.PyErr_SetObject(etype, op); Runtime.Decref(etype); }
internal static void SetupExceptionHack() { ns_exc = ClassManager.GetClass(typeof(Exception)).pyHandle; cache = new Hashtable(); string code = "import exceptions\n" + "class Exception(exceptions.Exception):\n" + " _class = None\n" + " _inner = None\n" + "\n" + " def __init__(self, *args, **kw):\n" + " inst = self.__class__._class(*args, **kw)\n" + " self.__dict__['_inner'] = inst\n" + " exceptions.Exception.__init__(self, *args, **kw)\n" + "\n" + " def __getattr__(self, name, _marker=[]):\n" + " inner = self.__dict__['_inner']\n" + " v = getattr(inner, name, _marker)\n" + " if v is not _marker:\n" + " return v\n" + " v = self.__dict__.get(name, _marker)\n" + " if v is not _marker:\n" + " return v\n" + " raise AttributeError(name)\n" + "\n" + " def __setattr__(self, name, value):\n" + " inner = self.__dict__['_inner']\n" + " setattr(inner, name, value)\n" + "\n" + " def __str__(self):\n" + " inner = self.__dict__.get('_inner')\n" + " msg = getattr(inner, 'Message', '')\n" + " st = getattr(inner, 'StackTrace', '')\n" + " st = st and '\\n' + st or ''\n" + " return msg + st\n" + "\n"; IntPtr dict = Runtime.PyDict_New(); IntPtr builtins = Runtime.PyEval_GetBuiltins(); Runtime.PyDict_SetItemString(dict, "__builtins__", builtins); IntPtr namestr = Runtime.PyString_FromString("System"); Runtime.PyDict_SetItemString(dict, "__name__", namestr); Runtime.Decref(namestr); Runtime.PyDict_SetItemString(dict, "__file__", Runtime.PyNone); Runtime.PyDict_SetItemString(dict, "__doc__", Runtime.PyNone); IntPtr flag = Runtime.Py_file_input; IntPtr done = Runtime.PyRun_String(code, flag, dict, dict); os_exc = Runtime.PyDict_GetItemString(dict, "Exception"); Runtime.PyObject_SetAttrString(os_exc, "_class", ns_exc); Runtime.PyErr_Clear(); }
/// <summary> /// Repr Method /// </summary> /// /// <remarks> /// Return a string representation of the object. This method is /// the managed equivalent of the Python expression "repr(object)". /// </remarks> public string Repr() { IntPtr strval = Runtime.PyObject_Repr(obj); string result = Runtime.GetManagedString(strval); Runtime.Decref(strval); return(result); }
//==================================================================== // ConstructorBinding dealloc implementation. //==================================================================== public static new void tp_dealloc(IntPtr ob) { BoundContructor self = (BoundContructor)GetManagedObject(ob); Runtime.Decref(self.repr); Runtime.Decref(self.pyTypeHndl); ExtensionType.FinalizeObject(self); }
//==================================================================== // ConstructorBinding dealloc implementation. //==================================================================== public static new void tp_dealloc(IntPtr ob) { ConstructorBinding self = (ConstructorBinding)GetManagedObject(ob); Runtime.Decref(self.repr); Runtime.Decref(self.pyTypeHndl); ExtensionType.FinalizeObject(self); }
/// <summary> /// ToString Method /// </summary> /// /// <remarks> /// Return the string representation of the object. This method is /// the managed equivalent of the Python expression "str(object)". /// </remarks> public override string ToString() { IntPtr strval = Runtime.PyObject_Unicode(obj); string result = Runtime.GetManagedString(strval); Runtime.Decref(strval); return(result); }
//==================================================================== // Descriptor dealloc implementation. //==================================================================== public static new void tp_dealloc(IntPtr ob) { EventObject self = (EventObject)GetManagedObject(ob); if (self.unbound != null) { Runtime.Decref(self.unbound.pyHandle); } ExtensionType.FinalizeObject(self); }
public static void tp_dealloc(IntPtr ob) { ManagedType self = GetManagedObject(ob); IntPtr dict = Marshal.ReadIntPtr(ob, ObjectOffset.ob_dict); Runtime.Decref(dict); Runtime.PyObject_GC_UnTrack(self.pyHandle); Runtime.PyObject_GC_Del(self.pyHandle); Runtime.Decref(self.tpHandle); self.gcHandle.Free(); }
//=================================================================== // Cleanup resources upon shutdown of the Python runtime. //=================================================================== internal static void Shutdown() { Type type = typeof(Exceptions); foreach (FieldInfo fi in type.GetFields(BindingFlags.Public | BindingFlags.Static)) { IntPtr op = (IntPtr)fi.GetValue(type); Runtime.Decref(op); } }
//=================================================================== // Cleanup resources upon shutdown of the Python runtime. //=================================================================== internal static void Shutdown() { #if (PYTHON32 || PYTHON33 || PYTHON34) Runtime.Decref(py_clr_module); Runtime.Decref(root.pyHandle); ModuleDefOffset.FreeModuleDef(module_def); #else Runtime.Decref(root.pyHandle); Runtime.Decref(root.pyHandle); #endif Runtime.Decref(py_import); }
static void SetConversionError(IntPtr value, Type target) { IntPtr ob = Runtime.PyObject_Repr(value); string src = Runtime.GetManagedString(ob); Runtime.Decref(ob); string error = String.Format( "Cannot convert {0} to {1}", src, target ); Exceptions.SetError(Exceptions.TypeError, error); }
public static PyObject RunString(string code, IntPtr globals, IntPtr locals) { IntPtr flag = (IntPtr)257; /* Py_file_input */ IntPtr result = Runtime.PyRun_String(code, flag, globals, locals); Runtime.Decref(locals); if (result == IntPtr.Zero) { return(null); } return(new PyObject(result)); }
/// <summary> /// Dispose Method /// </summary> /// /// <remarks> /// The Dispose method provides a way to explicitly release the /// Python object represented by a PyObject instance. It is a good /// idea to call Dispose on PyObjects that wrap resources that are /// limited or need strict lifetime control. Otherwise, references /// to Python objects will not be released until a managed garbage /// collection occurs. /// </remarks> protected virtual void Dispose(bool disposing) { if (!disposed) { if (Runtime.Py_IsInitialized() > 0) { IntPtr gs = PythonEngine.AcquireLock(); Runtime.Decref(obj); obj = IntPtr.Zero; PythonEngine.ReleaseLock(gs); } disposed = true; } }
public static void Finalize(IPythonDerivedType obj) { FieldInfo fi = obj.GetType().GetField("__pyobj__"); CLRObject self = (CLRObject)fi.GetValue(obj); // If python's been terminated then just free the gchandle. lock (Runtime.IsFinalizingLock) { if (0 == Runtime.Py_IsInitialized() || Runtime.IsFinalizing) { self.gcHandle.Free(); return; } } // delete the python object in an asnyc task as we may not be able to acquire // the GIL immediately and we don't want to block the GC thread. var t = Task.Factory.StartNew(() => { lock (Runtime.IsFinalizingLock) { // If python's been terminated then just free the gchandle. if (0 == Runtime.Py_IsInitialized() || Runtime.IsFinalizing) { self.gcHandle.Free(); return; } IntPtr gs = Runtime.PyGILState_Ensure(); try { // the C# object is being destroyed which must mean there are no more // references to the Python object as well so now we can dealloc the // python object. IntPtr dict = Marshal.ReadIntPtr(self.pyHandle, ObjectOffset.DictOffset(self.pyHandle)); if (dict != IntPtr.Zero) { Runtime.Decref(dict); } Runtime.PyObject_GC_Del(self.pyHandle); self.gcHandle.Free(); } finally { Runtime.PyGILState_Release(gs); } } }); }
/// <summary> /// Dispose Method /// </summary> /// /// <remarks> /// The Dispose method provides a way to explicitly release the /// Python object represented by a PyObject instance. It is a good /// idea to call Dispose on PyObjects that wrap resources that are /// limited or need strict lifetime control. Otherwise, references /// to Python objects will not be released until a managed garbage /// collection occurs. /// </remarks> public void Dispose() { if (!disposed) { if (Runtime.Py_IsInitialized() > 0) { IntPtr gs = PythonEngine.AcquireLock(); Runtime.Decref(obj); obj = IntPtr.Zero; PythonEngine.ReleaseLock(gs); } GC.SuppressFinalize(this); disposed = true; } }
//==================================================================== // 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)); }
//==================================================================== // Convert a Python value to a correctly typed managed array instance. // The Python value must support the Python sequence protocol and the // items in the sequence must be convertible to the target array type. //==================================================================== static bool ToArray(IntPtr value, Type obType, out Object result, bool setError) { Type elementType = obType.GetElementType(); int size = Runtime.PySequence_Size(value); result = null; if (size < 0) { if (setError) { SetConversionError(value, obType); } return(false); } Array items = Array.CreateInstance(elementType, size); // XXX - is there a better way to unwrap this if it is a real // array? for (int i = 0; i < size; i++) { Object obj = null; IntPtr item = Runtime.PySequence_GetItem(value, i); if (item == IntPtr.Zero) { if (setError) { SetConversionError(value, obType); return(false); } } if (!Converter.ToManaged(item, elementType, out obj, true)) { Runtime.Decref(item); return(false); } items.SetValue(obj, i); Runtime.Decref(item); } result = items; return(true); }
/// <summary> /// Allows ctor selection to be limited to a single attempt at a /// match by providing the MethodBase to use instead of searching /// the entire MethodBinder.list (generic ArrayList) /// </summary> /// <param name="inst"> (possibly null) instance </param> /// <param name="args"> PyObject* to the arg tuple </param> /// <param name="kw"> PyObject* to the keyword args dict </param> /// <param name="info"> The sole ContructorInfo to use or null </param> /// <returns> The result of the constructor call with converted params </returns> /// <remarks> /// 2010-07-24 BC: I added the info parameter to the call to Bind() /// Binding binding = this.Bind(inst, args, kw, info); /// to take advantage of Bind()'s ability to use a single MethodBase (CI or MI). /// </remarks> internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info) { Binding binding = this.Bind(inst, args, kw, info); Object result; if (binding == null) { // It is possible for __new__ to be invoked on construction // of a Python subclass of a managed class, so args may // reflect more args than are required to instantiate the // class. So if we cant find a ctor that matches, we'll see // if there is a default constructor and, if so, assume that // any extra args are intended for the subclass' __init__. IntPtr eargs = Runtime.PyTuple_New(0); binding = this.Bind(inst, eargs, kw); Runtime.Decref(eargs); if (binding == null) { Exceptions.SetError(Exceptions.TypeError, "no constructor matches given arguments" ); return(null); } } // Fire the selected ctor and catch errors... ConstructorInfo ci = (ConstructorInfo)binding.info; // Object construction is presumed to be non-blocking and fast // enough that we shouldn't really need to release the GIL. try { result = ci.Invoke(binding.args); } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } Exceptions.SetError(e); return(null); } return(result); }
//==================================================================== // Metatype __call__ implementation. This is needed to ensure correct // initialization (__init__ support), because the tp_call we inherit // from PyType_Type won't call __init__ for metatypes it doesnt know. //==================================================================== public static IntPtr tp_call(IntPtr tp, IntPtr args, IntPtr kw) { IntPtr func = Marshal.ReadIntPtr(tp, TypeOffset.tp_new); if (func == IntPtr.Zero) { return(Exceptions.RaiseTypeError("invalid object")); } IntPtr obj = NativeCall.Call_3(func, tp, args, kw); if (obj == IntPtr.Zero) { return(IntPtr.Zero); } IntPtr py__init__ = Runtime.PyString_FromString("__init__"); IntPtr type = Runtime.PyObject_TYPE(obj); IntPtr init = Runtime._PyType_Lookup(type, py__init__); Runtime.Decref(py__init__); Runtime.PyErr_Clear(); if (init != IntPtr.Zero) { IntPtr bound = Runtime.GetBoundArgTuple(obj, args); if (bound == IntPtr.Zero) { Runtime.Decref(obj); return(IntPtr.Zero); } IntPtr result = Runtime.PyObject_Call(init, bound, kw); Runtime.Decref(bound); if (result == IntPtr.Zero) { Runtime.Decref(obj); return(IntPtr.Zero); } Runtime.Decref(result); } return(obj); }
public CLRModule() : base("clr") { _namespace = String.Empty; // This hackery is required in order to allow a plain Python to // import the managed runtime via the CLR bootstrapper module. // The standard Python machinery in control at the time of the // import requires the module to pass PyModule_Check. :( if (!hacked) { IntPtr type = this.tpHandle; IntPtr mro = Marshal.ReadIntPtr(type, TypeOffset.tp_mro); IntPtr ext = Runtime.ExtendTuple(mro, Runtime.PyModuleType); Marshal.WriteIntPtr(type, TypeOffset.tp_mro, ext); Runtime.Decref(mro); hacked = true; } }
public object TrueDispatch(ArrayList args) { MethodInfo method = dtype.GetMethod("Invoke"); ParameterInfo[] pi = method.GetParameters(); IntPtr pyargs = Runtime.PyTuple_New(pi.Length); Type rtype = method.ReturnType; for (int i = 0; i < pi.Length; i++) { // Here we own the reference to the Python value, and we // give the ownership to the arg tuple. IntPtr arg = Converter.ToPython(args[i], pi[i].ParameterType); Runtime.PyTuple_SetItem(pyargs, i, arg); } IntPtr op = Runtime.PyObject_Call(target, pyargs, IntPtr.Zero); Runtime.Decref(pyargs); if (op == IntPtr.Zero) { PythonException e = new PythonException(); throw e; } if (rtype == typeof(void)) { return(null); } Object result = null; if (!Converter.ToManaged(op, rtype, out result, false)) { string s = "could not convert Python result to " + rtype.ToString(); Runtime.Decref(op); throw new ConversionException(s); } Runtime.Decref(op); return(result); }