This class provides the public interface of the Python runtime.
Beispiel #1
0
        private object ExecutePythonScriptCode(string code)
        {
            Python.Included.Installer.SetupPython().Wait();

            if (!PythonEngine.IsInitialized)
            {
                PythonEngine.Initialize();
                PythonEngine.BeginAllowThreads();
            }

            using (Py.GIL())
            {
                var result = Scope.Eval(code);
                return(CPythonEvaluator.OutputMarshaler.Marshal(result));
            }
        }
Beispiel #2
0
 public void Dispose()
 {
     if (Scope != null)
     {
         if (!PythonEngine.IsInitialized)
         {
             PythonEngine.Initialize();
             PythonEngine.BeginAllowThreads();
         }
         try
         {
             using (Py.GIL())
             {
                 Scope.Dispose();
             }
         }
         catch {}
     }
 }
Beispiel #3
0
        public DSCPythonCodeCompletionProviderCore()
        {
            VariableTypes = new Dictionary <string, Type>();
            ImportedTypes = new Dictionary <string, Type>();
            ClrModules    = new HashSet <string>();
            BadStatements = new Dictionary <string, int>();
            Guid pythonScopeGUID = Guid.NewGuid();

            uniquePythonScopeName += pythonScopeGUID.ToString();

            // Special case for python variables defined as null
            ImportedTypes["None"] = null;

            BasicVariableTypes = new List <Tuple <Regex, Type> >();

            BasicVariableTypes.Add(Tuple.Create(STRING_VARIABLE, typeof(PyString)));
            BasicVariableTypes.Add(Tuple.Create(DOUBLE_VARIABLE, typeof(PyFloat)));
            BasicVariableTypes.Add(Tuple.Create(INT_VARIABLE, typeof(PyInt)));
            BasicVariableTypes.Add(Tuple.Create(LIST_VARIABLE, typeof(PyList)));
            BasicVariableTypes.Add(Tuple.Create(DICT_VARIABLE, typeof(PyDict)));

            if (!PythonEngine.IsInitialized)
            {
                PythonEngine.Initialize();
                PythonEngine.BeginAllowThreads();
            }

            try
            {
                using (Py.GIL())
                {
                    if (GlobalScope == null)
                    {
                        GlobalScope = CreateGlobalScope();
                    }

                    if (Scope == null)
                    {
                        Scope = CreateUniquePythonScope();
                    }

                    var assemblies = AppDomain.CurrentDomain.GetAssemblies();

                    // Determine if the Revit API is available in the given context
                    if (assemblies.Any(x => x.GetName().Name == "RevitAPI"))
                    {
                        // Try to load Revit Type for autocomplete
                        try
                        {
                            var revitImports =
                                "import clr\nclr.AddReference('RevitAPI')\nclr.AddReference('RevitAPIUI')\nfrom Autodesk.Revit.DB import *\nimport Autodesk\n";

                            Scope.Exec(revitImports);

                            ClrModules.Add("RevitAPI");
                            ClrModules.Add("RevitAPIUI");
                        }
                        catch
                        {
                            Log("Failed to load Revit types for autocomplete. Python autocomplete will not see Autodesk namespace types.");
                        }
                    }

                    // Determine if the ProtoGeometry is available in the given context
                    if (assemblies.Any(x => x.GetName().Name == "ProtoGeometry"))
                    {
                        // Try to load ProtoGeometry Type for autocomplete
                        try
                        {
                            var libGImports =
                                "import clr\nclr.AddReference('ProtoGeometry')\nfrom Autodesk.DesignScript.Geometry import *\n";

                            Scope.Exec(libGImports);
                            ClrModules.Add("ProtoGeometry");
                        }
                        catch (Exception e)
                        {
                            Log(e.ToString());
                            Log("Failed to load ProtoGeometry types for autocomplete. Python autocomplete will not see Autodesk namespace types.");
                        }
                    }

                    // PythonNet evaluates basic types as Python native types:
                    // Ex: a = ""
                    // type(a) will have the value {class str} and not the clr System.String
                    //
                    // Populate the basic types after python is initialized
                    // These instance types will correspond to Python basic types (no clr)
                    // ex. PyString("") => Python's {class str}
                    // PyInt(0) => Python's {class int}
                    basicPyObjects = new Dictionary <Type, PyObject>();
                    basicPyObjects[typeof(PyString)] = new PyString("");
                    basicPyObjects[typeof(PyFloat)]  = new PyFloat(0);
                    basicPyObjects[typeof(PyInt)]    = new PyInt(0);
                    basicPyObjects[typeof(PyList)]   = new PyList();
                    basicPyObjects[typeof(PyDict)]   = new PyDict();
                }
            }
            catch {}
        }
Beispiel #4
0
 public static PyObject Import(string name)
 {
     return(PythonEngine.ImportModule(name));
 }
Beispiel #5
0
        /// <summary>
        /// Generate completion data for the specified text, while import the given types into the
        /// scope and discovering variable assignments.
        /// </summary>
        /// <param name="code">The code to parse</param>
        /// <param name="expand">Determines if the entire namespace should be used</param>
        /// <returns>Return a list of IExternalCodeCompletionData </returns>
        public override IExternalCodeCompletionData[] GetCompletionData(string code, bool expand = false)
        {
            IEnumerable <PythonCodeCompletionDataCore> items = new List <PythonCodeCompletionDataCore>();

            if (!PythonEngine.IsInitialized)
            {
                PythonEngine.Initialize();
                PythonEngine.BeginAllowThreads();
            }

            try
            {
                using (Py.GIL())
                {
                    if (code.Contains("\"\"\""))
                    {
                        code = StripDocStrings(code);
                    }

                    UpdateImportedTypes(code);
                    UpdateVariableTypes(code);  // Possibly use hindley-milner in the future

                    // If expand param is true use the entire namespace from the line of code
                    // Else just return the last name of the namespace
                    string name = expand ? GetLastNameSpace(code) : GetLastName(code);
                    if (!String.IsNullOrEmpty(name))
                    {
                        try
                        {
                            // Attempt to get type using naming
                            Type type = expand ? TryGetTypeFromFullName(name) : TryGetType(name);
                            // CLR type
                            if (type != null)
                            {
                                items = EnumerateMembers(type, name).Select(x => new PythonCodeCompletionDataCore(x.Item1, x.Item2, x.Item3, x.Item4, this));
                            }
                            // Variable assignment types
                            else if (VariableTypes.TryGetValue(name, out type))
                            {
                                if (basicPyObjects.TryGetValue(type, out PyObject basicObj))
                                {
                                    items = EnumerateMembers(basicObj, name).Select(x => new PythonCodeCompletionDataCore(x.Item1, x.Item2, x.Item3, x.Item4, this));
                                }
                                else
                                {
                                    items = EnumerateMembers(type, name).Select(x => new PythonCodeCompletionDataCore(x.Item1, x.Item2, x.Item3, x.Item4, this));
                                }
                            }
                            else
                            {
                                // Try to find the corresponding PyObject from the python environment
                                // Most types should be successfully retrieved at this stage
                                var pyObj = LookupObject(name);
                                if (pyObj != null)
                                {
                                    items = EnumerateMembers(pyObj, name).Select(x => new PythonCodeCompletionDataCore(x.Item1, x.Item2, x.Item3, x.Item4, this));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Log(ex.ToString());
                        }
                    }
                }
            }
            catch {}

            // If unable to find matching results and expand was set to false,
            // try again using the full namespace (set expand to true)
            if (!items.Any() && !expand)
            {
                return(GetCompletionData(code, true));
            }

            return(items.ToArray());
        }
Beispiel #6
0
        /// <summary>
        /// Initialize Method
        /// </summary>
        /// <remarks>
        /// Initialize the Python runtime. It is safe to call this method
        /// more than once, though initialization will only happen on the
        /// first call. It is *not* necessary to hold the Python global
        /// interpreter lock (GIL) to call this method.
        /// initSigs can be set to 1 to do default python signal configuration. This will override the way signals are handled by the application.
        /// </remarks>
        public static void Initialize(IEnumerable <string> args, bool setSysArgv = true, bool initSigs = false)
        {
            if (!initialized)
            {
                // Creating the delegateManager MUST happen before Runtime.Initialize
                // is called. If it happens afterwards, DelegateManager's CodeGenerator
                // throws an exception in its ctor.  This exception is eaten somehow
                // during an initial "import clr", and the world ends shortly thereafter.
                // This is probably masking some bad mojo happening somewhere in Runtime.Initialize().
                delegateManager = new DelegateManager();
                Runtime.Initialize(initSigs);
                initialized = true;
                Exceptions.Clear();

                // Make sure we clean up properly on app domain unload.
                AppDomain.CurrentDomain.DomainUnload += OnDomainUnload;

                // Remember to shut down the runtime.
                AddShutdownHandler(Runtime.Shutdown);

                // The global scope gets used implicitly quite early on, remember
                // to clear it out when we shut down.
                AddShutdownHandler(PyScopeManager.Global.Clear);

                if (setSysArgv)
                {
                    Py.SetArgv(args);
                }

                // register the atexit callback (this doesn't use Py_AtExit as the C atexit
                // callbacks are called after python is fully finalized but the python ones
                // are called while the python engine is still running).
                string code =
                    "import atexit, clr\n" +
                    "atexit.register(clr._AtExit)\n";
                PythonEngine.Exec(code);

                // Load the clr.py resource into the clr module
                IntPtr clr      = Python.Runtime.ImportHook.GetCLRModule();
                IntPtr clr_dict = Runtime.PyModule_GetDict(clr);

                var locals = new PyDict();
                try
                {
                    IntPtr module         = Runtime.PyImport_AddModule("clr._extras");
                    IntPtr module_globals = Runtime.PyModule_GetDict(module);
                    IntPtr builtins       = Runtime.PyEval_GetBuiltins();
                    Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins);

                    Assembly assembly = Assembly.GetExecutingAssembly();
                    string[] names    = assembly.GetManifestResourceNames();
                    using (Stream stream = assembly.GetManifestResourceStream("Python.Runtime.NetCore.resources.clr.py"))
                        using (var reader = new StreamReader(stream))
                        {
                            // add the contents of clr.py to the module
                            string clr_py = reader.ReadToEnd();
                            Exec(clr_py, module_globals, locals.Handle);
                        }

                    // add the imported module to the clr module, and copy the API functions
                    // and decorators into the main clr module.
                    Runtime.PyDict_SetItemString(clr_dict, "_extras", module);
                    foreach (PyObject key in locals.Keys())
                    {
                        if (!key.ToString().StartsWith("_") || key.ToString().Equals("__version__"))
                        {
                            PyObject value = locals[key];
                            Runtime.PyDict_SetItem(clr_dict, key.Handle, value.Handle);
                            value.Dispose();
                        }
                        key.Dispose();
                    }
                }
                finally
                {
                    locals.Dispose();
                }
            }
        }
Beispiel #7
0
 internal GILState()
 {
     state = PythonEngine.AcquireLock();
 }
Beispiel #8
0
 public void Dispose()
 {
     PythonEngine.ReleaseLock(state);
     GC.SuppressFinalize(this);
 }
Beispiel #9
0
        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)
            {
                var value = new StringBuilder("No method matches given arguments");
                if (methodinfo != null && methodinfo.Length > 0)
                {
                    value.Append($" for {methodinfo[0].Name}");
                }

                long argCount = Runtime.PyTuple_Size(args);
                value.Append(": (");
                for (long argIndex = 0; argIndex < argCount; argIndex++)
                {
                    var arg = Runtime.PyTuple_GetItem(args, argIndex);
                    if (arg != IntPtr.Zero)
                    {
                        var type = Runtime.PyObject_Type(arg);
                        if (type != IntPtr.Zero)
                        {
                            try {
                                var description = Runtime.PyObject_Unicode(type);
                                if (description != IntPtr.Zero)
                                {
                                    value.Append(Runtime.GetManagedString(description));
                                    Runtime.XDecref(description);
                                }
                            } finally {
                                Runtime.XDecref(type);
                            }
                        }
                    }

                    if (argIndex + 1 < argCount)
                    {
                        value.Append(", ");
                    }
                }
                value.Append(')');
                Exceptions.SetError(Exceptions.TypeError, value.ToString());
                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.PyTuple_New(binding.outs + 1);
                IntPtr v = Converter.ToPython(result, mi.ReturnType);
                Runtime.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.PyTuple_SetItem(t, n, v);
                        n++;
                    }
                }

                if (binding.outs == 1 && mi.ReturnType == typeof(void))
                {
                    v = Runtime.PyTuple_GetItem(t, 1);
                    Runtime.XIncref(v);
                    Runtime.XDecref(t);
                    return(v);
                }

                return(t);
            }

            return(Converter.ToPython(result, mi.ReturnType));
        }
Beispiel #10
0
        static Converter()
        {
            nfi         = NumberFormatInfo.InvariantInfo;
            objectType  = typeof(Object);
            stringType  = typeof(String);
            int16Type   = typeof(Int16);
            int32Type   = typeof(Int32);
            int64Type   = typeof(Int64);
            singleType  = typeof(Single);
            doubleType  = typeof(Double);
            decimalType = typeof(Decimal);
            flagsType   = typeof(FlagsAttribute);
            boolType    = typeof(Boolean);
            typeType    = typeof(Type);

            IntPtr decimalMod = Runtime.PyImport_ImportModule("decimal");

            if (decimalMod == null)
            {
                throw new PythonException();
            }

            IntPtr dateTimeMod = Runtime.PyImport_ImportModule("datetime");

            if (dateTimeMod == null)
            {
                throw new PythonException();
            }

            decimalCtor = Runtime.PyObject_GetAttrString(decimalMod, "Decimal");
            if (decimalCtor == null)
            {
                throw new PythonException();
            }

            dateTimeCtor = Runtime.PyObject_GetAttrString(dateTimeMod, "datetime");
            if (dateTimeCtor == null)
            {
                throw new PythonException();
            }

            timeSpanCtor = Runtime.PyObject_GetAttrString(dateTimeMod, "timedelta");
            if (timeSpanCtor == null)
            {
                throw new PythonException();
            }

            IntPtr tzInfoMod = PythonEngine.ModuleFromString("custom_tzinfo",
                                                             "from datetime import timedelta, tzinfo\n" +
                                                             "class GMT(tzinfo):\n" +
                                                             "    def __init__(self, hours, minutes):\n" +
                                                             "        self.hours = hours\n" +
                                                             "        self.minutes = minutes\n" +
                                                             "    def utcoffset(self, dt):\n" +
                                                             "        return timedelta(hours=self.hours, minutes=self.minutes)\n" +
                                                             "    def tzname(self, dt):\n" +
                                                             "        return \"GMT {0:00}:{1:00}\".format(self.hours, self.minutes)\n" +
                                                             "    def dst (self, dt):\n" +
                                                             "        return timedelta(0)\n").Handle;

            tzInfoCtor = Runtime.PyObject_GetAttrString(tzInfoMod, "GMT");
            if (tzInfoCtor == null)
            {
                throw new PythonException();
            }
        }
Beispiel #11
0
        /// <summary>
        /// Initialize Method
        /// </summary>
        ///
        /// <remarks>
        /// Initialize the Python runtime. It is safe to call this method
        /// more than once, though initialization will only happen on the
        /// first call. It is *not* necessary to hold the Python global
        /// interpreter lock (GIL) to call this method.
        /// </remarks>
        public static void Initialize()
        {
            if (!initialized)
            {
                // Creating the delegateManager MUST happen before Runtime.Initialize
                // is called. If it happens afterwards, DelegateManager's CodeGenerator
                // throws an exception in its ctor.  This exception is eaten somehow
                // during an initial "import clr", and the world ends shortly thereafter.
                // This is probably masking some bad mojo happening somewhere in Runtime.Initialize().
                delegateManager = new DelegateManager();
                Runtime.Initialize();
                initialized = true;
                Exceptions.Clear();

                // register the atexit callback (this doesn't use Py_AtExit as the C atexit
                // callbacks are called after python is fully finalized but the python ones
                // are called while the python engine is still running).
                string code =
                    "import atexit, clr\n" +
                    "atexit.register(clr._AtExit)\n";
                PyObject r = PythonEngine.RunString(code);
                if (r != null)
                {
                    r.Dispose();
                }

                // Load the clr.py resource into the clr module
                IntPtr clr      = Python.Runtime.ImportHook.GetCLRModule();
                IntPtr clr_dict = Runtime.PyModule_GetDict(clr);

                PyDict locals = new PyDict();
                try
                {
                    IntPtr module         = Runtime.PyImport_AddModule("clr._extras");
                    IntPtr module_globals = Runtime.PyModule_GetDict(module);
                    IntPtr builtins       = Runtime.PyEval_GetBuiltins();
                    Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins);

                    var assembly = Assembly.GetExecutingAssembly();
                    using (Stream stream = assembly.GetManifestResourceStream("clr.py"))
                        using (StreamReader reader = new StreamReader(stream))
                        {
                            // add the contents of clr.py to the module
                            string   clr_py = reader.ReadToEnd();
                            PyObject result = RunString(clr_py, module_globals, locals.Handle);
                            if (null == result)
                            {
                                throw new PythonException();
                            }
                            result.Dispose();
                        }

                    // add the imported module to the clr module, and copy the API functions
                    // and decorators into the main clr module.
                    Runtime.PyDict_SetItemString(clr_dict, "_extras", module);
                    foreach (PyObject key in locals.Keys())
                    {
                        if (!key.ToString().StartsWith("_"))
                        {
                            PyObject value = locals[key];
                            Runtime.PyDict_SetItem(clr_dict, key.Handle, value.Handle);
                            value.Dispose();
                        }
                        key.Dispose();
                    }
                }
                finally
                {
                    locals.Dispose();
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// Descriptor __set__ implementation. This method sets the value of
        /// a property based on the given Python value. The Python value must
        /// be convertible to the type of the property.
        /// </summary>
        public new static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val)
        {
            var        self   = (PropertyObject)GetManagedObject(ds);
            MethodInfo setter = self.setter;
            object     newval;
            IntPtr     ts = IntPtr.Zero;

            if (val == IntPtr.Zero)
            {
                Exceptions.RaiseTypeError("cannot delete property");
                return(-1);
            }

            if (setter == null)
            {
                Exceptions.RaiseTypeError("property is read-only");
                return(-1);
            }


            if (!Converter.ToManaged(val, self.info.PropertyType, out newval, true))
            {
                return(-1);
            }

            bool is_static = setter.IsStatic;

            if (ob == IntPtr.Zero || ob == Runtime.PyNone)
            {
                if (!is_static)
                {
                    Exceptions.RaiseTypeError("instance property must be set on an instance");
                    return(-1);
                }
            }

            try
            {
                if (!is_static)
                {
                    var co = GetManagedObject(ob) as CLRObject;
                    if (co == null)
                    {
                        Exceptions.RaiseTypeError("invalid target");
                        return(-1);
                    }
                    ts = PythonEngine.BeginAllowThreads();
                    self.info.SetValue(co.inst, newval, null);
                }
                else
                {
                    ts = PythonEngine.BeginAllowThreads();
                    self.info.SetValue(null, newval, null);
                }
                PythonEngine.EndAllowThreads(ts);
                return(0);
            }
            catch (Exception e)
            {
                if (e.InnerException != null)
                {
                    e = e.InnerException;
                }

                if (IntPtr.Zero != ts)
                {
                    PythonEngine.EndAllowThreads(ts);
                }
                Exceptions.SetError(e);
                return(-1);
            }
        }
Beispiel #13
0
        /// <summary>
        /// Descriptor __get__ implementation. This method returns the
        /// value of the property on the given object. The returned value
        /// is converted to an appropriately typed Python object.
        /// </summary>
        public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp)
        {
            var        self   = (PropertyObject)GetManagedObject(ds);
            MethodInfo getter = self.getter;
            object     result;

            IntPtr ts = IntPtr.Zero;

            if (getter == null)
            {
                return(Exceptions.RaiseTypeError("property cannot be read"));
            }

            if (ob == IntPtr.Zero || ob == Runtime.PyNone)
            {
                if (!getter.IsStatic)
                {
                    Exceptions.SetError(Exceptions.TypeError,
                                        "instance property must be accessed through a class instance");
                    return(IntPtr.Zero);
                }

                ts = PythonEngine.BeginAllowThreads();
                try
                {
                    result = self.info.GetValue(null, null);
                    PythonEngine.EndAllowThreads(ts);
                    return(Converter.ToPython(result, self.info.PropertyType));
                }
                catch (Exception e)
                {
                    PythonEngine.EndAllowThreads(ts);
                    return(Exceptions.RaiseTypeError(e.Message));
                }
            }

            var co = GetManagedObject(ob) as CLRObject;

            if (co == null)
            {
                return(Exceptions.RaiseTypeError("invalid target"));
            }

            ts = PythonEngine.BeginAllowThreads();
            try
            {
                result = self.info.GetValue(co.inst, null);
                PythonEngine.EndAllowThreads(ts);
                return(Converter.ToPython(result, self.info.PropertyType));
            }
            catch (Exception e)
            {
                if (e.InnerException != null)
                {
                    e = e.InnerException;
                }
                PythonEngine.EndAllowThreads(ts);
                Exceptions.SetError(e);
                return(IntPtr.Zero);
            }
        }
Beispiel #14
0
        internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // No valid methods, nothing to bind.
            if (GetMethods().Length == 0)
            {
                var msg = new StringBuilder("The underlying C# method(s) have been deleted");
                if (list.Count > 0 && list[0].Name != null)
                {
                    msg.Append($": {list[0]}");
                }
                return(Exceptions.RaiseTypeError(msg.ToString()));
            }

            Binding binding = Bind(inst, args, kw, info, methodinfo);
            object  result;
            IntPtr  ts = IntPtr.Zero;

            if (binding == null)
            {
                var value = new StringBuilder("No method matches given arguments");
                if (methodinfo != null && methodinfo.Length > 0)
                {
                    value.Append($" for {methodinfo[0].Name}");
                }
                else if (list.Count > 0 && list[0].Valid)
                {
                    value.Append($" for {list[0].Value.Name}");
                }

                value.Append(": ");
                Runtime.PyErr_Fetch(out var errType, out var errVal, out var errTrace);
                AppendArgumentTypes(to: value, args);
                Runtime.PyErr_Restore(errType.StealNullable(), errVal.StealNullable(), errTrace.StealNullable());
                Exceptions.RaiseTypeError(value.ToString());
                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, if any, 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 > 0)
            {
                ParameterInfo[] pi = mi.GetParameters();
                int             c  = pi.Length;
                var             n  = 0;

                bool   isVoid    = mi.ReturnType == typeof(void);
                int    tupleSize = binding.outs + (isVoid ? 0 : 1);
                IntPtr t         = Runtime.PyTuple_New(tupleSize);
                if (!isVoid)
                {
                    IntPtr v = Converter.ToPython(result, mi.ReturnType);
                    Runtime.PyTuple_SetItem(t, n, v);
                    n++;
                }

                for (var i = 0; i < c; i++)
                {
                    Type pt = pi[i].ParameterType;
                    if (pt.IsByRef)
                    {
                        IntPtr v = Converter.ToPython(binding.args[i], pt.GetElementType());
                        Runtime.PyTuple_SetItem(t, n, v);
                        n++;
                    }
                }

                if (binding.outs == 1 && mi.ReturnType == typeof(void))
                {
                    IntPtr v = Runtime.PyTuple_GetItem(t, 0);
                    Runtime.XIncref(v);
                    Runtime.XDecref(t);
                    return(v);
                }

                return(t);
            }

            return(Converter.ToPython(result, mi.ReturnType));
        }
Beispiel #15
0
        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 for " + methodinfo[0].Name);
                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.PyTuple_New(binding.outs + 1);
                IntPtr v = Converter.ToPython(result, mi.ReturnType);
                Runtime.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.PyTuple_SetItem(t, n, v);
                        n++;
                    }
                }

                if (binding.outs == 1 && mi.ReturnType == typeof(void))
                {
                    v = Runtime.PyTuple_GetItem(t, 1);
                    Runtime.XIncref(v);
                    Runtime.XDecref(t);
                    return(v);
                }

                return(t);
            }

            return(Converter.ToPython(result, mi.ReturnType));
        }
Beispiel #16
0
 protected PyClrTypeBase(string pyType, Type clrType)
 {
     this.PythonType = PythonEngine.Eval(pyType);
     this.ClrType    = clrType;
 }