public static void InvokeSetProperty <T>(IPythonDerivedType obj, string propertyName, T value) { FieldInfo fi = obj.GetType().GetField("__pyobj__"); var self = (CLRObject)fi.GetValue(obj); if (null == self) { throw new NullReferenceException("Instance must be specified when setting a property"); } IntPtr gs = Runtime.PyGILState_Ensure(); try { Runtime.XIncref(self.pyHandle); using (var pyself = new PyObject(self.pyHandle)) using (var pyvalue = new PyObject(Converter.ToPythonImplicit(value))) { pyself.SetAttr(propertyName, pyvalue); } } finally { Runtime.PyGILState_Release(gs); } }
/// <summary> /// Implements support for the Python iteration protocol. /// </summary> public static IntPtr tp_iternext(IntPtr ob) { var self = GetManagedObject(ob) as Iterator; try { if (!self.iter.MoveNext()) { Exceptions.SetError(Exceptions.StopIteration, Runtime.PyNone); return(IntPtr.Zero); } } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } Exceptions.SetError(e); return(IntPtr.Zero); } object item = self.iter.Current; return(Converter.ToPythonImplicit(item)); }
public static IntPtr tp_iternext(IntPtr ob) { Iterator self = GetManagedObject(ob) as Iterator; if (!self.iter.MoveNext()) { Exceptions.SetError(Exceptions.StopIteration, Runtime.PyNone); return(IntPtr.Zero); } object item = self.iter.Current; return(Converter.ToPythonImplicit(item)); }
internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) { // Utility to create a subtype of a managed type with the ability for the // a python subtype able to override the managed implementation string name = Runtime.GetManagedString(py_name); // the derived class can have class attributes __assembly__ and __module__ which // control the name of the assembly and module the new type is created in. object assembly = null; object namespaceStr = null; var disposeList = new List <PyObject>(); try { var assemblyKey = new PyObject(Converter.ToPython("__assembly__", typeof(string))); disposeList.Add(assemblyKey); if (0 != Runtime.PyMapping_HasKey(py_dict, assemblyKey.Handle)) { var pyAssembly = new PyObject(Runtime.PyDict_GetItem(py_dict, assemblyKey.Handle)); Runtime.XIncref(pyAssembly.Handle); disposeList.Add(pyAssembly); if (!Converter.ToManagedValue(pyAssembly.Handle, typeof(string), out assembly, false)) { throw new InvalidCastException("Couldn't convert __assembly__ value to string"); } } var namespaceKey = new PyObject(Converter.ToPythonImplicit("__namespace__")); disposeList.Add(namespaceKey); if (0 != Runtime.PyMapping_HasKey(py_dict, namespaceKey.Handle)) { var pyNamespace = new PyObject(Runtime.PyDict_GetItem(py_dict, namespaceKey.Handle)); Runtime.XIncref(pyNamespace.Handle); disposeList.Add(pyNamespace); if (!Converter.ToManagedValue(pyNamespace.Handle, typeof(string), out namespaceStr, false)) { throw new InvalidCastException("Couldn't convert __namespace__ value to string"); } } } finally { foreach (PyObject o in disposeList) { o.Dispose(); } } // create the new managed type subclassing the base managed type var baseClass = ManagedType.GetManagedObject(py_base_type) as ClassBase; if (null == baseClass) { return(Exceptions.RaiseTypeError("invalid base class, expected CLR class type")); } try { Type subType = ClassDerivedObject.CreateDerivedType(name, baseClass.type, py_dict, (string)namespaceStr, (string)assembly); // create the new ManagedType and python type ClassBase subClass = ClassManager.GetClass(subType); IntPtr py_type = GetTypeHandle(subClass, subType); // by default the class dict will have all the C# methods in it, but as this is a // derived class we want the python overrides in there instead if they exist. IntPtr cls_dict = Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict); Runtime.PyDict_Update(cls_dict, py_dict); return(py_type); } catch (Exception e) { return(Exceptions.RaiseTypeError(e.Message)); } }
public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, string origMethodName, object[] args) { FieldInfo fi = obj.GetType().GetField("__pyobj__"); var self = (CLRObject)fi.GetValue(obj); if (null != self) { var disposeList = new List <PyObject>(); IntPtr gs = Runtime.PyGILState_Ensure(); try { Runtime.XIncref(self.pyHandle); var pyself = new PyObject(self.pyHandle); disposeList.Add(pyself); Runtime.XIncref(Runtime.PyNone); var 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 overridden then it will be a managed object ManagedType managedMethod = ManagedType.GetManagedObject(method.Handle); if (null == managedMethod) { var pyargs = new PyObject[args.Length]; for (var i = 0; i < args.Length; ++i) { pyargs[i] = new PyObject(Converter.ToPythonImplicit(args[i])); disposeList.Add(pyargs[i]); } PyObject py_result = method.Invoke(pyargs); disposeList.Add(py_result); return; } } } finally { foreach (PyObject x in disposeList) { x?.Dispose(); } Runtime.PyGILState_Release(gs); } } if (origMethodName == null) { throw new NotImplementedException($"Python object does not have a '{methodName}' method"); } obj.GetType().InvokeMember(origMethodName, BindingFlags.InvokeMethod, null, obj, args); }
//==================================================================== // This is the implementaion of the overriden methods in the derived // type. It looks for a python method with the same name as the method // on the managed base class and if it exists and isn't the managed // method binding (ie it has been overriden in the derived python // class) it calls it, otherwise it calls the base method. //==================================================================== public static T InvokeMethod <T>(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.ToPythonImplicit(args[i])); disposeList.Add(pyargs[i]); } PyObject py_result = method.Invoke(pyargs); disposeList.Add(py_result); return((T)py_result.AsManagedObject(typeof(T))); } } } finally { foreach (PyObject x in disposeList) { if (x != null) { x.Dispose(); } } Runtime.PyGILState_Release(gs); } } if (origMethodName == null) { throw new NullReferenceException("Python object does not have a '" + methodName + "' method"); } return((T)obj.GetType().InvokeMember(origMethodName, BindingFlags.InvokeMethod, null, obj, args)); }