Пример #1
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();
                    using (Stream stream = assembly.GetManifestResourceStream("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();
                }
            }
        }
Пример #2
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);
            }

            //allow_threads = true breaks the code with passing pyobjects to clr functions.
            //I think this happens because python is not thread safe and objects cannot be called
            //different threads
            allow_threads = false;
            if (allow_threads)
            {
                Console.WriteLine("ALLOW THR");
                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);
            }


            if (mi.ReturnType == typeof(QuantApp.Kernel.JVM.JVMObject))
            {
                dynamic pymodule = Py.Import("clr");
                result = pymodule.createJVM(result);
            }

            return(Converter.ToPython(result, mi.ReturnType));
        }