forked from panda3d/panda3d
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathp3dPythonRun.h
More file actions
207 lines (170 loc) · 6.05 KB
/
p3dPythonRun.h
File metadata and controls
207 lines (170 loc) · 6.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/**
* 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."
*
* @file p3dPythonRun.h
* @author drose
* @date 2009-06-05
*/
#ifndef P3DPYTHONRUN_H
#define P3DPYTHONRUN_H
#include "pandabase.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "run_p3dpython.h"
#include "p3d_lock.h"
#include "handleStream.h"
#include "p3dCInstance.h"
#include "pandaFileStreamBuf.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
/**
* 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(const char *program_name, const char *archive_file,
FHandle input_handle, FHandle output_handle,
const char *log_pathname, bool interactive_console);
~P3DPythonRun();
int run_python();
void set_window_open(P3DCInstance *inst, bool is_open);
void request_keyboard_focus(P3DCInstance *inst);
private:
void run_interactive_console();
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 send_windows_message(int id, unsigned int msg, int wparam, int lparam);
void terminate_session();
private:
TiXmlElement *pyobj_to_xml(PyObject *value);
PyObject *xml_to_pyobj(TiXmlElement *xvalue);
private:
// This subclass of WindowHandle is associated with the parent window we are
// given by the parent process. We use it to add hooks for communicating
// with the parent window, for instance to ask for the parent window to
// manage keyboard focus when necessary.
class P3DWindowHandle : public WindowHandle {
public:
P3DWindowHandle(P3DPythonRun *p3dpython, P3DCInstance *inst,
const WindowHandle ©);
public:
virtual void attach_child(WindowHandle *child);
virtual void detach_child(WindowHandle *child);
virtual void request_keyboard_focus(WindowHandle *child);
private:
P3DPythonRun *_p3dpython;
P3DCInstance *_inst;
int _child_count;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
WindowHandle::init_type();
register_type(_type_handle, "P3DWindowHandle",
WindowHandle::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
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;
Filename _archive_file;
int _py_argc;
#if PY_MAJOR_VERSION >= 3
wchar_t *_py_argv[2];
std::wstring _program_name;
#else
char *_py_argv[2];
std::string _program_name;
#endif
bool _interactive_console;
PyObject *_runner;
PyObject *_undefined_object_class;
PyObject *_undefined;
PyObject *_concrete_struct_class;
PyObject *_browser_object_class;
PyObject *_taskMgr;
// 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;
pofstream _error_log;
bool _read_thread_continue;
bool _program_continue;
bool _session_terminated;
THREAD _read_thread;
public:
static P3DPythonRun *_global_ptr;
};
#include "p3dPythonRun.I"
#endif