| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- // Filename: p3dPythonRun.h
- // Created by: drose (05Jun09)
- //
- ////////////////////////////////////////////////////////////////////
- //
- // PANDA 3D SOFTWARE
- // Copyright (c) Carnegie Mellon University. All rights reserved.
- //
- // All use of this software is subject to the terms of the revised BSD
- // license. You should have received a copy of this license along
- // with this source code in a file named "LICENSE."
- //
- ////////////////////////////////////////////////////////////////////
- #ifndef P3DPYTHONRUN_H
- #define P3DPYTHONRUN_H
- #include "pandabase.h"
- #ifdef _WIN32
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #endif
- #include "p3d_lock.h"
- #include "handleStream.h"
- #include "p3dCInstance.h"
- #include "pythonTask.h"
- #include "pmap.h"
- #include "pdeque.h"
- #include "pmutex.h"
- #include "get_tinyxml.h"
- #include "filename.h"
- #include <Python.h>
- // Python 2.5 adds Py_ssize_t; earlier versions don't have it.
- #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
- typedef int Py_ssize_t;
- #define PY_SSIZE_T_MAX INT_MAX
- #define PY_SSIZE_T_MIN INT_MIN
- #endif
- using namespace std;
- ////////////////////////////////////////////////////////////////////
- // Class : P3DPythonRun
- // Description : This class is used to run, and communicate with,
- // embedded Python in a sub-process. It is compiled and
- // launched as a separate executable from the p3d_plugin
- // dll, because that's the only way Windows can launch a
- // sub-process, and also because it makes it possible to
- // compile-time link with Panda and Python, instead of
- // having to go through the clumsy dynamic-loading
- // interface.
- //
- // Communication is via XML files exchanged via
- // anonymous pipes from the parent process. This isn't
- // terribly eficient, of course, but it's easy; and it's
- // a fairly low-bandwidth channel so efficiency is not
- // paramount.
- //
- // This executable is not designed to stand alone; it is
- // designed to be invoked only by p3d_plugin.
- ////////////////////////////////////////////////////////////////////
- class P3DPythonRun {
- public:
- P3DPythonRun(int argc, char *argv[]);
- ~P3DPythonRun();
- bool run_python();
- private:
- void handle_command(TiXmlDocument *doc);
- void handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
- int want_response_id);
- void handle_script_response_command(TiXmlElement *xcommand);
- void check_comm();
- static PyObject *st_check_comm(PyObject *, PyObject *args);
- TiXmlDocument *wait_script_response(int response_id);
- PyObject *py_request_func(PyObject *args);
- static PyObject *st_request_func(PyObject *, PyObject *args);
- void spawn_read_thread();
- void join_read_thread();
- void start_instance(P3DCInstance *inst, TiXmlElement *xinstance);
- void terminate_instance(int id);
- void set_instance_info(P3DCInstance *inst, TiXmlElement *xinstance);
- void add_package_info(P3DCInstance *inst, TiXmlElement *xpackage);
- void set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams);
- void setup_window(int id, TiXmlElement *xwparams);
- void setup_window(P3DCInstance *inst, TiXmlElement *xwparams);
-
- void terminate_session();
- private:
- TiXmlElement *pyobj_to_xml(PyObject *value);
- PyObject *xml_to_pyobj(TiXmlElement *xvalue);
- private:
- // This method runs only within the read thread.
- THREAD_CALLBACK_DECLARATION(P3DPythonRun, rt_thread_run);
- void rt_thread_run();
- private:
- typedef pmap<int, P3DCInstance *> Instances;
- Instances _instances;
- int _session_id;
- string _program_name;
- Filename _archive_file;
- int _py_argc;
- char **_py_argv;
- PyObject *_runner;
- PyObject *_undefined_object_class;
- PyObject *_undefined;
- PyObject *_concrete_struct_class;
- PyObject *_browser_object_class;
- PyObject *_taskMgr;
- PT(PythonTask) _check_comm_task;
- // This map keeps track of the PyObject pointers we have delivered
- // to the parent process. We have to hold the reference count on
- // each of these until the parent process tells us it's safe to
- // release them.
- typedef pmap<int, PyObject *> SentObjects;
- SentObjects _sent_objects;
- int _next_sent_id;
- typedef pdeque<TiXmlDocument *> Commands;
- // This is a special queue of responses extracted from the _commands
- // queue, below. It's protected by the Panda mutex.
- Commands _responses;
- Mutex _responses_lock;
- // The remaining members are manipulated by the read thread.
- Commands _commands;
-
- // This has to be an actual OS LOCK instead of Panda's Mutex,
- // because we have to use a true thread here, not one of Panda's
- // simple threads.
- LOCK _commands_lock;
- HandleStream _pipe_read;
- HandleStream _pipe_write;
- bool _read_thread_continue;
- bool _program_continue;
- THREAD _read_thread;
- public:
- static P3DPythonRun *_global_ptr;
- };
- #include "p3dPythonRun.I"
- #endif
|