private static void SetVariable(IntPtr?globals, string key, IntPtr value) { CpyRuntime.PyDict_SetItemString( pointer: globals.Value, key: key, value: value ); }
private void SetupBuiltins(ref ScriptRuntime runtime) { // get builtins IntPtr builtins = CpyRuntime.PyEval_GetBuiltins(); // Add timestamp and executuin uuid SetVariable(builtins, "__execid__", runtime.ExecId); SetVariable(builtins, "__timestamp__", runtime.ExecTimestamp); // set builtins SetVariable(builtins, "__cachedengine__", RecoveredFromCache); SetVariable(builtins, "__cachedengineid__", TypeId); SetVariable(builtins, "__scriptruntime__", runtime); if (runtime.UIApp != null) { SetVariable(builtins, "__revit__", runtime.UIApp); } else if (runtime.UIControlledApp != null) { SetVariable(builtins, "__revit__", runtime.UIControlledApp); } else if (runtime.App != null) { SetVariable(builtins, "__revit__", runtime.App); } else { SetVariable(builtins, "__revit__", null); } // Adding data provided by IExternalCommand.Execute SetVariable(builtins, "__commanddata__", runtime.ScriptRuntimeConfigs.CommandData); SetVariable(builtins, "__elements__", runtime.ScriptRuntimeConfigs.SelectedElements); // Add ui button handle SetVariable(builtins, "__uibutton__", runtime.UIControl); // Adding information on the command being executed SetVariable(builtins, "__commandpath__", Path.GetDirectoryName(runtime.ScriptData.ScriptPath)); SetVariable(builtins, "__configcommandpath__", Path.GetDirectoryName(runtime.ScriptData.ConfigScriptPath)); SetVariable(builtins, "__commandname__", runtime.ScriptData.CommandName); SetVariable(builtins, "__commandbundle__", runtime.ScriptData.CommandBundle); SetVariable(builtins, "__commandextension__", runtime.ScriptData.CommandExtension); SetVariable(builtins, "__commanduniqueid__", runtime.ScriptData.CommandUniqueId); SetVariable(builtins, "__commandcontrolid__", runtime.ScriptData.CommandControlId); SetVariable(builtins, "__forceddebugmode__", runtime.ScriptRuntimeConfigs.DebugMode); SetVariable(builtins, "__shiftclick__", runtime.ScriptRuntimeConfigs.ConfigMode); // Add reference to the results dictionary // so the command can add custom values for logging SetVariable(builtins, "__result__", runtime.GetResultsDictionary()); // EVENT HOOKS BUILTINS ---------------------------------------------------------------------------------- // set event arguments for engine SetVariable(builtins, "__eventsender__", runtime.ScriptRuntimeConfigs.EventSender); SetVariable(builtins, "__eventargs__", runtime.ScriptRuntimeConfigs.EventArgs); }
public static void DomainReloadAndGC() { Assert.IsFalse(PythonEngine.IsInitialized); RunAssemblyAndUnload("test1"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); RunAssemblyAndUnload("test2"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); }
public override ValueType Execute(ValueType arg) { const string code = @" from Python.EmbeddingTest.Domain import MyClass def test_obj_call(): obj = MyClass() obj.Method() obj.StaticMethod() obj.Property = 1 obj.Field = 10 test_obj_call() "; const string name = "test_domain_reload_mod"; using (Py.GIL()) { // Create a new module IntPtr module = PyRuntime.PyModule_New(name); Assert.That(module != IntPtr.Zero); IntPtr globals = PyRuntime.PyObject_GetAttrString(module, "__dict__"); Assert.That(globals != IntPtr.Zero); try { // import builtins // module.__dict__[__builtins__] = builtins int res = PyRuntime.PyDict_SetItemString(globals, "__builtins__", PyRuntime.PyEval_GetBuiltins()); PythonException.ThrowIfIsNotZero(res); // Execute the code in the module's scope PythonEngine.Exec(code, globals); // import sys // modules = sys.modules IntPtr modules = PyRuntime.PyImport_GetModuleDict(); // modules[name] = module res = PyRuntime.PyDict_SetItemString(modules, name, module); PythonException.ThrowIfIsNotZero(res); } catch { PyRuntime.XDecref(module); throw; } finally { PyRuntime.XDecref(globals); } return(module); } }
private void StoreSearchPaths() { var currentSysPath = GetSysPaths(); _sysPaths = new List <string>(); long itemsCount = currentSysPath.Length(); for (long i = 0; i < itemsCount; i++) { BorrowedReference item = CpyRuntime.PyList_GetItem(currentSysPath.Handle, i); string path = CpyRuntime.GetManagedString(item); _sysPaths.Add(path); } }
public override ValueType Execute(ValueType arg) { var module = (IntPtr)arg; using (Py.GIL()) { var test_obj_call = PyRuntime.PyObject_GetAttrString(module, "test_obj_call"); PythonException.ThrowIfIsNull(test_obj_call); var args = PyRuntime.PyTuple_New(0); var res = PyRuntime.PyObject_CallObject(test_obj_call, args); PythonException.ThrowIfIsNull(res); PyRuntime.XDecref(args); PyRuntime.XDecref(res); } return 0; }
static void RunDomainReloadSteps <T1, T2>() where T1 : CrossCaller where T2 : CrossCaller { ValueType arg = null; Type type = typeof(Proxy); { AppDomain domain = CreateDomain("test_domain_reload_1"); try { var theProxy = CreateInstanceInstanceAndUnwrap <Proxy>(domain); theProxy.Call("InitPython", ShutdownMode.Reload); var caller = CreateInstanceInstanceAndUnwrap <T1>(domain); arg = caller.Execute(arg); theProxy.Call("ShutdownPython"); } finally { AppDomain.Unload(domain); } } { AppDomain domain = CreateDomain("test_domain_reload_2"); try { var theProxy = CreateInstanceInstanceAndUnwrap <Proxy>(domain); theProxy.Call("InitPython", ShutdownMode.Reload); var caller = CreateInstanceInstanceAndUnwrap <T2>(domain); caller.Execute(arg); theProxy.Call("ShutdownPythonCompletely"); } finally { AppDomain.Unload(domain); } } if (PythonEngine.DefaultShutdownMode == ShutdownMode.Normal) { Assert.IsTrue(PyRuntime.Py_IsInitialized() == 0); } }
public static void DomainReloadAndGC() { Assert.IsFalse(PythonEngine.IsInitialized); RunAssemblyAndUnload("test1"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); RunAssemblyAndUnload("test2"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); if (PythonEngine.DefaultShutdownMode == ShutdownMode.Normal) { // The default mode is a normal mode, // it should shutdown the Python VM avoiding influence other tests. PyRuntime.PyGILState_Ensure(); PyRuntime.Py_Finalize(); } }
static void RunDomainReloadSteps <T1, T2>() where T1 : CrossCaller where T2 : CrossCaller { ValueType arg = null; Type type = typeof(Proxy); { AppDomain domain = CreateDomain("test_domain_reload_1"); try { var theProxy = CreateInstanceInstanceAndUnwrap <Proxy>(domain); theProxy.Call(nameof(PythonRunner.InitPython), PyRuntime.PythonDLL); var caller = CreateInstanceInstanceAndUnwrap <T1>(domain); arg = caller.Execute(arg); theProxy.Call("ShutdownPython"); } finally { AppDomain.Unload(domain); } } { AppDomain domain = CreateDomain("test_domain_reload_2"); try { var theProxy = CreateInstanceInstanceAndUnwrap <Proxy>(domain); theProxy.Call(nameof(PythonRunner.InitPython), PyRuntime.PythonDLL); var caller = CreateInstanceInstanceAndUnwrap <T2>(domain); caller.Execute(arg); theProxy.Call("ShutdownPythonCompletely"); } finally { AppDomain.Unload(domain); } } Assert.IsTrue(PyRuntime.Py_IsInitialized() != 0); }
public void ConvertOverflow() { using (var num = new PyInt(ulong.MaxValue)) { using var largeNum = PyRuntime.PyNumber_Add(num, num); try { object value; foreach (var type in _numTypes) { bool res = Converter.ToManaged(largeNum.BorrowOrThrow(), type, out value, true); Assert.IsFalse(res); Assert.IsTrue(Exceptions.ExceptionMatches(Exceptions.OverflowError)); Exceptions.Clear(); } } finally { Exceptions.Clear(); } } }
public override ValueType Execute(ValueType arg) { try { // Create a C# user-defined object in Python. Asssing some values. Type type = typeof(Python.EmbeddingTest.Domain.MyClass); string code = string.Format(@" import clr clr.AddReference('{0}') from Python.EmbeddingTest.Domain import MyClass obj = MyClass() obj.Method() obj.StaticMethod() obj.Property = 1 obj.Field = 10 ", Assembly.GetExecutingAssembly().FullName); using (Py.GIL()) using (var scope = Py.CreateScope()) { scope.Exec(code); using (PyObject obj = scope.Get("obj")) { Debug.Assert(obj.AsManagedObject(type).GetType() == type); // We only needs its Python handle PyRuntime.XIncref(obj.Handle); return(obj.Handle); } } } catch (Exception e) { Debug.WriteLine(e); throw; } }
/// <summary> /// Convert a Python value to an instance of a primitive managed type. /// </summary> private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError) { IntPtr overflow = Exceptions.OverflowError; TypeCode tc = Type.GetTypeCode(obType); result = null; IntPtr op; int ival; switch (tc) { case TypeCode.String: string st = Runtime.GetManagedString(value); if (st == null) { goto type_error; } result = st; return(true); case TypeCode.Int32: // Trickery to support 64-bit platforms. if (Runtime.IsPython2 && Runtime.Is32Bit) { op = Runtime.PyNumber_Int(value); // As of Python 2.3, large ints magically convert :( if (Runtime.PyLong_Check(op)) { Runtime.XDecref(op); goto overflow; } if (op == IntPtr.Zero) { if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); Runtime.XDecref(op); result = ival; return(true); } else // Python3 always use PyLong API { op = Runtime.PyNumber_Long(value); if (op == IntPtr.Zero) { Exceptions.Clear(); if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } long ll = (long)Runtime.PyLong_AsLongLong(op); Runtime.XDecref(op); if (ll == -1 && Exceptions.ErrorOccurred()) { goto overflow; } if (ll > Int32.MaxValue || ll < Int32.MinValue) { goto overflow; } result = (int)ll; return(true); } case TypeCode.Boolean: result = Runtime.PyObject_IsTrue(value) != 0; return(true); case TypeCode.Byte: #if PYTHON3 if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType)) { if (Runtime.PyBytes_Size(value) == 1) { op = Runtime.PyBytes_AS_STRING(value); result = (byte)Marshal.ReadByte(op); return(true); } goto type_error; } #elif PYTHON2 if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) { if (Runtime.PyString_Size(value) == 1) { op = Runtime.PyString_AsString(value); result = (byte)Marshal.ReadByte(op); return(true); } goto type_error; } #endif op = Runtime.PyNumber_Int(value); if (op == IntPtr.Zero) { if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); Runtime.XDecref(op); if (ival > Byte.MaxValue || ival < Byte.MinValue) { goto overflow; } byte b = (byte)ival; result = b; return(true); case TypeCode.SByte: #if PYTHON3 if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType)) { if (Runtime.PyBytes_Size(value) == 1) { op = Runtime.PyBytes_AS_STRING(value); result = (byte)Marshal.ReadByte(op); return(true); } goto type_error; } #elif PYTHON2 if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) { if (Runtime.PyString_Size(value) == 1) { op = Runtime.PyString_AsString(value); result = (sbyte)Marshal.ReadByte(op); return(true); } goto type_error; } #endif op = Runtime.PyNumber_Int(value); if (op == IntPtr.Zero) { if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); Runtime.XDecref(op); if (ival > SByte.MaxValue || ival < SByte.MinValue) { goto overflow; } sbyte sb = (sbyte)ival; result = sb; return(true); case TypeCode.Char: #if PYTHON3 if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType)) { if (Runtime.PyBytes_Size(value) == 1) { op = Runtime.PyBytes_AS_STRING(value); result = (byte)Marshal.ReadByte(op); return(true); } goto type_error; } #elif PYTHON2 if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) { if (Runtime.PyString_Size(value) == 1) { op = Runtime.PyString_AsString(value); result = (char)Marshal.ReadByte(op); return(true); } goto type_error; } #endif else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType)) { if (Runtime.PyUnicode_GetSize(value) == 1) { op = Runtime.PyUnicode_AsUnicode(value); Char[] buff = new Char[1]; Marshal.Copy(op, buff, 0, 1); result = buff[0]; return(true); } goto type_error; } op = Runtime.PyNumber_Int(value); if (op == IntPtr.Zero) { goto type_error; } ival = Runtime.PyInt_AsLong(op); Runtime.XDecref(op); if (ival > Char.MaxValue || ival < Char.MinValue) { goto overflow; } result = (char)ival; return(true); case TypeCode.Int16: op = Runtime.PyNumber_Int(value); if (op == IntPtr.Zero) { if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); Runtime.XDecref(op); if (ival > Int16.MaxValue || ival < Int16.MinValue) { goto overflow; } short s = (short)ival; result = s; return(true); case TypeCode.Int64: op = Runtime.PyNumber_Long(value); if (op == IntPtr.Zero) { if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } long l = (long)Runtime.PyLong_AsLongLong(op); Runtime.XDecref(op); if ((l == -1) && Exceptions.ErrorOccurred()) { goto overflow; } result = l; return(true); case TypeCode.UInt16: op = Runtime.PyNumber_Int(value); if (op == IntPtr.Zero) { if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); Runtime.XDecref(op); if (ival > UInt16.MaxValue || ival < UInt16.MinValue) { goto overflow; } ushort us = (ushort)ival; result = us; return(true); case TypeCode.UInt32: op = Runtime.PyNumber_Long(value); if (op == IntPtr.Zero) { if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } uint ui = (uint)Runtime.PyLong_AsUnsignedLong(op); if (Exceptions.ErrorOccurred()) { Runtime.XDecref(op); goto overflow; } IntPtr check = Runtime.PyLong_FromUnsignedLong(ui); int err = Runtime.PyObject_Compare(check, op); Runtime.XDecref(check); Runtime.XDecref(op); if (0 != err || Exceptions.ErrorOccurred()) { goto overflow; } result = ui; return(true); case TypeCode.UInt64: op = Runtime.PyNumber_Long(value); if (op == IntPtr.Zero) { if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } ulong ul = (ulong)Runtime.PyLong_AsUnsignedLongLong(op); Runtime.XDecref(op); if (Exceptions.ErrorOccurred()) { goto overflow; } result = ul; return(true); case TypeCode.Single: op = Runtime.PyNumber_Float(value); if (op == IntPtr.Zero) { if (Exceptions.ExceptionMatches(overflow)) { goto overflow; } goto type_error; } double dd = Runtime.PyFloat_AsDouble(op); Runtime.CheckExceptionOccurred(); Runtime.XDecref(op); if (dd > Single.MaxValue || dd < Single.MinValue) { if (!double.IsInfinity(dd)) { goto overflow; } } result = (float)dd; return(true); case TypeCode.Double: op = Runtime.PyNumber_Float(value); if (op == IntPtr.Zero) { goto type_error; } double d = Runtime.PyFloat_AsDouble(op); Runtime.CheckExceptionOccurred(); Runtime.XDecref(op); result = d; return(true); } type_error: if (setError) { string tpName = Runtime.PyObject_GetTypeName(value); Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}"); } return(false); overflow: if (setError) { Exceptions.SetError(Exceptions.OverflowError, "value too large to convert"); } return(false); }
protected override void OnSave(InterDomainContext context) { base.OnSave(context); Runtime.XIncref(target); Runtime.XIncref(targetType); }
/// <summary> /// MethodBinding __call__ implementation. /// </summary> public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) { var 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) { var len = Runtime.PyTuple_Size(args); //FIXME: Never used 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. var disposeList = new List <IntPtr>(); try { IntPtr target = self.target; if (target == IntPtr.Zero && !self.m.IsStatic()) { var len = Runtime.PyTuple_Size(args); if (len < 1) { Exceptions.SetError(Exceptions.TypeError, "not enough arguments"); return(IntPtr.Zero); } target = Runtime.PyTuple_GetItem(args, 0); Runtime.XIncref(target); disposeList.Add(target); args = Runtime.PyTuple_GetSlice(args, 1, len); disposeList.Add(args); } // if the class is a IPythonDerivedClass and target is not the same as self.targetType // (eg if calling the base class method) then call the original base class method instead // of the target method. IntPtr superType = IntPtr.Zero; if (Runtime.PyObject_TYPE(target) != self.targetType) { var inst = GetManagedObject(target) as CLRObject; if (inst?.inst is IPythonDerivedType) { var baseType = GetManagedObject(self.targetType) as ClassBase; if (baseType != null) { string baseMethodName = "_" + baseType.type.Name + "__" + self.m.name; IntPtr baseMethod = Runtime.PyObject_GetAttrString(target, baseMethodName); if (baseMethod != IntPtr.Zero) { var baseSelf = GetManagedObject(baseMethod) as MethodBinding; if (baseSelf != null) { self = baseSelf; } Runtime.XDecref(baseMethod); } else { Runtime.PyErr_Clear(); } } } } return(self.m.Invoke(target, args, kw, self.info)); } finally { foreach (IntPtr ptr in disposeList) { Runtime.XDecref(ptr); } } }
/// <summary> /// Standard comparison implementation for instances of reflected types. /// </summary> public static IntPtr tp_richcompare(IntPtr ob, IntPtr other, int op) { CLRObject co1; CLRObject co2; switch (op) { case Runtime.Py_EQ: case Runtime.Py_NE: 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; } if (ob == other) { Runtime.XIncref(pytrue); return(pytrue); } co1 = GetManagedObject(ob) as CLRObject; co2 = GetManagedObject(other) as CLRObject; if (null == co2) { Runtime.XIncref(pyfalse); return(pyfalse); } object o1 = co1.inst; object o2 = co2.inst; if (Equals(o1, o2)) { Runtime.XIncref(pytrue); return(pytrue); } Runtime.XIncref(pyfalse); return(pyfalse); case Runtime.Py_LT: case Runtime.Py_LE: case Runtime.Py_GT: case Runtime.Py_GE: co1 = GetManagedObject(ob) as CLRObject; co2 = GetManagedObject(other) as CLRObject; if (co1 == null || co2 == null) { return(Exceptions.RaiseTypeError("Cannot get managed object")); } var co1Comp = co1.inst as IComparable; if (co1Comp == null) { Type co1Type = co1.GetType(); return(Exceptions.RaiseTypeError($"Cannot convert object of type {co1Type} to IComparable")); } try { int cmp = co1Comp.CompareTo(co2.inst); IntPtr pyCmp; if (cmp < 0) { if (op == Runtime.Py_LT || op == Runtime.Py_LE) { pyCmp = Runtime.PyTrue; } else { pyCmp = Runtime.PyFalse; } } else if (cmp == 0) { if (op == Runtime.Py_LE || op == Runtime.Py_GE) { pyCmp = Runtime.PyTrue; } else { pyCmp = Runtime.PyFalse; } } else { if (op == Runtime.Py_GE || op == Runtime.Py_GT) { pyCmp = Runtime.PyTrue; } else { pyCmp = Runtime.PyFalse; } } Runtime.XIncref(pyCmp); return(pyCmp); } catch (ArgumentException e) { return(Exceptions.RaiseTypeError(e.Message)); } default: Runtime.XIncref(Runtime.PyNotImplemented); return(Runtime.PyNotImplemented); } }
private void ClearMembers() { Runtime.Py_CLEAR(ref target); Runtime.Py_CLEAR(ref targetType); }
internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo) { // loop to find match, return invoker w/ or /wo error MethodBase[] _methods = null; int pynargs = Runtime.Interop.PyTuple_Size(args); object arg; var isGeneric = false; ArrayList defaultArgList = null; if (info != null) { _methods = new MethodBase[1]; _methods.SetValue(info, 0); } else { _methods = GetMethods(); } Type clrtype; // TODO: Clean up foreach (MethodBase mi in _methods) { if (mi.IsGenericMethod) { isGeneric = true; } ParameterInfo[] pi = mi.GetParameters(); int clrnargs = pi.Length; var match = false; int arrayStart = -1; var outs = 0; if (pynargs == clrnargs) { match = true; } else if (pynargs < clrnargs) { match = true; defaultArgList = new ArrayList(); for (int v = pynargs; v < clrnargs; v++) { if (pi[v].DefaultValue == DBNull.Value) { match = false; } else { defaultArgList.Add(pi[v].DefaultValue); } } } else if (pynargs > clrnargs && clrnargs > 0 && Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute))) { // This is a `foo(params object[] bar)` style method match = true; arrayStart = clrnargs - 1; } if (match) { var margs = new object[clrnargs]; for (var n = 0; n < clrnargs; n++) { IntPtr op; if (n < pynargs) { if (arrayStart == n) { // map remaining Python arguments to a tuple since // the managed function accepts it - hopefully :] op = Runtime.Interop.PyTuple_GetSlice(args, arrayStart, pynargs); } else { op = Runtime.Interop.PyTuple_GetItem(args, n); } // this logic below handles cases when multiple overloading methods // are ambiguous, hence comparison between Python and CLR types // is necessary clrtype = null; IntPtr pyoptype; if (_methods.Length > 1) { pyoptype = IntPtr.Zero; pyoptype = Runtime.PyObject_Type(op); Exceptions.Clear(); if (pyoptype != IntPtr.Zero) { clrtype = Converter.GetTypeByAlias(pyoptype); } Runtime.XDecref(pyoptype); } if (clrtype != null) { var typematch = false; if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype)) { IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType); pyoptype = Runtime.PyObject_Type(op); Exceptions.Clear(); if (pyoptype != IntPtr.Zero) { if (pytype != pyoptype) { typematch = false; } else { typematch = true; clrtype = pi[n].ParameterType; } } if (!typematch) { // this takes care of enum values TypeCode argtypecode = Type.GetTypeCode(pi[n].ParameterType); TypeCode paramtypecode = Type.GetTypeCode(clrtype); if (argtypecode == paramtypecode) { typematch = true; clrtype = pi[n].ParameterType; } } Runtime.XDecref(pyoptype); if (!typematch) { margs = null; break; } } else { typematch = true; clrtype = pi[n].ParameterType; } } else { clrtype = pi[n].ParameterType; } if (pi[n].IsOut || clrtype.IsByRef) { outs++; } if (!Converter.ToManaged(op, clrtype, out arg, false)) { Exceptions.Clear(); margs = null; break; } if (arrayStart == n) { // GetSlice() creates a new reference but GetItem() // returns only a borrow reference. Runtime.XDecref(op); } margs[n] = arg; } else { if (defaultArgList != null) { margs[n] = defaultArgList[n - pynargs]; } } } if (margs == null) { continue; } object target = null; if (!mi.IsStatic && inst != IntPtr.Zero) { //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst); // InvalidCastException: Unable to cast object of type // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject' var co = ManagedType.GetManagedObject(inst) as CLRObject; // Sanity check: this ensures a graceful exit if someone does // something intentionally wrong like call a non-static method // on the class rather than on an instance of the class. // XXX maybe better to do this before all the other rigmarole. if (co == null) { return(null); } target = co.inst; } return(new Binding(mi, target, margs, outs)); } } // We weren't able to find a matching method but at least one // is a generic method and info is null. That happens when a generic // method was not called using the [] syntax. Let's introspect the // type of the arguments and use it to construct the correct method. if (isGeneric && info == null && methodinfo != null) { Type[] types = Runtime.PythonArgsToTypeArray(args, true); MethodInfo mi = MatchParameters(methodinfo, types); return(Bind(inst, args, kw, mi, null)); } return(null); }
internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo) { Binding binding = Bind(inst, args, kw, info, methodinfo); object result; IntPtr ts = IntPtr.Zero; if (binding == null) { Exceptions.SetError(Exceptions.TypeError, "No method matches given arguments"); return(IntPtr.Zero); } if (allow_threads) { ts = PythonEngine.BeginAllowThreads(); } try { result = binding.info.Invoke(binding.inst, BindingFlags.Default, null, binding.args, null); } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } if (allow_threads) { PythonEngine.EndAllowThreads(ts); } Exceptions.SetError(e); return(IntPtr.Zero); } if (allow_threads) { PythonEngine.EndAllowThreads(ts); } // If there are out parameters, we return a tuple containing // the result followed by the out parameters. If there is only // one out parameter and the return type of the method is void, // we return the out parameter as the result to Python (for // code compatibility with ironpython). var mi = (MethodInfo)binding.info; if (binding.outs == 1 && mi.ReturnType == typeof(void)) { } if (binding.outs > 0) { ParameterInfo[] pi = mi.GetParameters(); int c = pi.Length; var n = 0; IntPtr t = Runtime.Interop.PyTuple_New(binding.outs + 1); IntPtr v = Converter.ToPython(result, mi.ReturnType); Runtime.Interop.PyTuple_SetItem(t, n, v); n++; for (var i = 0; i < c; i++) { Type pt = pi[i].ParameterType; if (pi[i].IsOut || pt.IsByRef) { v = Converter.ToPython(binding.args[i], pt); Runtime.Interop.PyTuple_SetItem(t, n, v); n++; } } if (binding.outs == 1 && mi.ReturnType == typeof(void)) { v = Runtime.Interop.PyTuple_GetItem(t, 1); Runtime.XIncref(v); Runtime.XDecref(t); return(v); } return(t); } return(Converter.ToPython(result, mi.ReturnType)); }
internal static IntPtr ToPython(object value, Type type) { if (value is PyObject) { IntPtr handle = ((PyObject)value).Handle; Runtime.XIncref(handle); return(handle); } IntPtr result = IntPtr.Zero; // Null always converts to None in Python. if (value == null) { result = Runtime.PyNone; Runtime.XIncref(result); return(result); } if (value is IList && !(value is INotifyPropertyChanged) && value.GetType().IsGenericType) { using (var resultlist = new PyList()) { foreach (object o in (IEnumerable)value) { using (var p = new PyObject(ToPython(o, o?.GetType()))) { resultlist.Append(p); } } Runtime.XIncref(resultlist.Handle); return(resultlist.Handle); } } // it the type is a python subclass of a managed type then return the // underlying python object rather than construct a new wrapper object. var pyderived = value as IPythonDerivedType; if (null != pyderived) { #if NETSTANDARD return(ClassDerivedObject.ToPython(pyderived)); #else // if object is remote don't do this if (!System.Runtime.Remoting.RemotingServices.IsTransparentProxy(pyderived)) { return(ClassDerivedObject.ToPython(pyderived)); } #endif } // hmm - from Python, we almost never care what the declared // type is. we'd rather have the object bound to the actual // implementing class. type = value.GetType(); TypeCode tc = Type.GetTypeCode(type); switch (tc) { case TypeCode.Object: return(CLRObject.GetInstHandle(value, type)); case TypeCode.String: return(Runtime.PyUnicode_FromString((string)value)); case TypeCode.Int32: return(Runtime.PyInt_FromInt32((int)value)); case TypeCode.Boolean: if ((bool)value) { Runtime.XIncref(Runtime.PyTrue); return(Runtime.PyTrue); } Runtime.XIncref(Runtime.PyFalse); return(Runtime.PyFalse); case TypeCode.Byte: return(Runtime.PyInt_FromInt32((int)((byte)value))); case TypeCode.Char: return(Runtime.PyUnicode_FromOrdinal((int)((char)value))); case TypeCode.Int16: return(Runtime.PyInt_FromInt32((int)((short)value))); case TypeCode.Int64: return(Runtime.PyLong_FromLongLong((long)value)); case TypeCode.Single: // return Runtime.PyFloat_FromDouble((double)((float)value)); string ss = ((float)value).ToString(nfi); IntPtr ps = Runtime.PyString_FromString(ss); IntPtr op = Runtime.PyFloat_FromString(ps, IntPtr.Zero); Runtime.XDecref(ps); return(op); case TypeCode.Double: return(Runtime.PyFloat_FromDouble((double)value)); case TypeCode.SByte: return(Runtime.PyInt_FromInt32((int)((sbyte)value))); case TypeCode.UInt16: return(Runtime.PyInt_FromInt32((int)((ushort)value))); case TypeCode.UInt32: return(Runtime.PyLong_FromUnsignedLong((uint)value)); case TypeCode.UInt64: return(Runtime.PyLong_FromUnsignedLongLong((ulong)value)); default: if (value is IEnumerable) { using (var resultlist = new PyList()) { foreach (object o in (IEnumerable)value) { using (var p = new PyObject(ToPython(o, o?.GetType()))) { resultlist.Append(p); } } Runtime.XIncref(resultlist.Handle); return(resultlist.Handle); } } result = CLRObject.GetInstHandle(value, type); return(result); } }
internal static bool ToManagedValue(IntPtr value, Type obType, out object result, bool setError) { if (obType == typeof(PyObject)) { Runtime.XIncref(value); // PyObject() assumes ownership result = new PyObject(value); return(true); } // Common case: if the Python value is a wrapped managed object // instance, just return the wrapped object. ManagedType mt = ManagedType.GetManagedObject(value); result = null; if (mt != null) { if (mt is CLRObject) { object tmp = ((CLRObject)mt).inst; if (obType.IsInstanceOfType(tmp)) { result = tmp; return(true); } Exceptions.SetError(Exceptions.TypeError, $"value cannot be converted to {obType}"); return(false); } if (mt is ClassBase) { result = ((ClassBase)mt).type; return(true); } // shouldn't happen return(false); } if (value == Runtime.PyNone && !obType.IsValueType) { result = null; return(true); } if (obType.IsGenericType && obType.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (value == Runtime.PyNone) { result = null; return(true); } // Set type to underlying type obType = obType.GetGenericArguments()[0]; } if (obType.IsArray) { return(ToArray(value, obType, out result, setError)); } if (obType.IsEnum) { return(ToEnum(value, obType, out result, setError)); } // Conversion to 'Object' is done based on some reasonable default // conversions (Python string -> managed string, Python int -> Int32 etc.). if (obType == objectType) { if (Runtime.IsStringType(value)) { return(ToPrimitive(value, stringType, out result, setError)); } if (Runtime.PyBool_Check(value)) { return(ToPrimitive(value, boolType, out result, setError)); } if (Runtime.PyInt_Check(value)) { return(ToPrimitive(value, int32Type, out result, setError)); } if (Runtime.PyLong_Check(value)) { return(ToPrimitive(value, int64Type, out result, setError)); } if (Runtime.PyFloat_Check(value)) { return(ToPrimitive(value, doubleType, out result, setError)); } if (Runtime.PySequence_Check(value)) { return(ToArray(value, typeof(object[]), out result, setError)); } Runtime.XIncref(value); // PyObject() assumes ownership result = new PyObject(value); return(true); } // Conversion to 'Type' is done using the same mappings as above for objects. if (obType == typeType) { if (value == Runtime.PyStringType) { result = stringType; return(true); } if (value == Runtime.PyBoolType) { result = boolType; return(true); } if (value == Runtime.PyIntType) { result = int32Type; return(true); } if (value == Runtime.PyLongType) { result = int64Type; return(true); } if (value == Runtime.PyFloatType) { result = doubleType; return(true); } if (value == Runtime.PyListType || value == Runtime.PyTupleType) { result = typeof(object[]); return(true); } if (setError) { Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Type"); } return(false); } return(ToPrimitive(value, obType, out result, setError)); }
public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) { // Replacement for the builtin __import__. The original import // hook is saved as this.py_import. This version handles CLR // import and defers to the normal builtin for everything else. int num_args = Runtime.PyTuple_Size(args); if (num_args < 1) { return(Exceptions.RaiseTypeError( "__import__() takes at least 1 argument (0 given)" )); } // borrowed reference IntPtr py_mod_name = Runtime.PyTuple_GetItem(args, 0); if ((py_mod_name == IntPtr.Zero) || (!Runtime.IsStringType(py_mod_name))) { return(Exceptions.RaiseTypeError("string expected")); } // Check whether the import is of the form 'from x import y'. // This determines whether we return the head or tail module. IntPtr fromList = IntPtr.Zero; bool fromlist = false; if (num_args >= 4) { fromList = Runtime.PyTuple_GetItem(args, 3); if ((fromList != IntPtr.Zero) && (Runtime.PyObject_IsTrue(fromList) == 1)) { fromlist = true; } } string mod_name = Runtime.GetManagedString(py_mod_name); if (mod_name == "CLR" || mod_name == "clr") { Runtime.Incref(root.pyHandle); return(root.pyHandle); } string realname = mod_name; if (mod_name.StartsWith("CLR.")) { realname = mod_name.Substring(4); } string[] names = realname.Split('.'); // Now we need to decide if the name refers to a CLR module, // and may have to do an implicit load (for b/w compatibility) // using the AssemblyManager. The assembly manager tries // really hard not to use Python objects or APIs, because // parts of it can run recursively and on strange threads. // // It does need an opportunity from time to time to check to // see if sys.path has changed, in a context that is safe. Here // we know we have the GIL, so we'll let it update if needed. AssemblyManager.UpdatePath(); AssemblyManager.LoadImplicit(realname); if (!AssemblyManager.IsValidNamespace(realname)) { return(Runtime.PyObject_Call(py_import, args, kw)); } // See if sys.modules for this interpreter already has the // requested module. If so, just return the exising module. IntPtr modules = Runtime.PyImport_GetModuleDict(); IntPtr module = Runtime.PyDict_GetItem(modules, py_mod_name); if (module != IntPtr.Zero) { if (fromlist) { Runtime.Incref(module); return(module); } module = Runtime.PyDict_GetItemString(modules, names[0]); Runtime.Incref(module); return(module); } Exceptions.Clear(); // Traverse the qualified module name to get the named module // and place references in sys.modules as we go. Note that if // we are running in interactive mode we pre-load the names in // each module, which is often useful for introspection. If we // are not interactive, we stick to just-in-time creation of // objects at lookup time, which is much more efficient. if (preload < 0) { if (Runtime.PySys_GetObject("ps1") != IntPtr.Zero) { preload = 1; } else { Exceptions.Clear(); preload = 0; } } ModuleObject head = (mod_name == realname) ? null : root; ModuleObject tail = root; for (int i = 0; i < names.Length; i++) { string name = names[i]; ManagedType mt = tail.GetAttribute(name); if (!(mt is ModuleObject)) { string error = String.Format("No module named {0}", name); Exceptions.SetError(Exceptions.ImportError, error); return(IntPtr.Zero); } if (head == null) { head = (ModuleObject)mt; } tail = (ModuleObject)mt; if (preload == 1) { tail.LoadNames(); } Runtime.PyDict_SetItemString(modules, tail.moduleName, tail.pyHandle ); } ModuleObject mod = fromlist ? tail : head; if (fromlist && Runtime.PySequence_Size(fromList) == 1) { IntPtr fp = Runtime.PySequence_GetItem(fromList, 0); if ((preload < 1) && Runtime.GetManagedString(fp) == "*") { mod.LoadNames(); } Runtime.Decref(fp); } Runtime.Incref(mod.pyHandle); return(mod.pyHandle); }
/// <summary> /// return the variable dict of the scope. /// </summary> /// <returns></returns> public PyDict Variables() { Runtime.XIncref(variables); return(new PyDict(variables)); }
//=================================================================== // Cleanup resources upon shutdown of the Python runtime. //=================================================================== internal static void Shutdown() { Runtime.Decref(root.pyHandle); Runtime.Decref(py_import); }