mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
p3dpython can be a Panda app
This commit is contained in:
parent
506154a6b6
commit
b660d0f3e5
@ -1,6 +1,6 @@
|
|||||||
// This directory is still experimental. Define HAVE_P3D_PLUGIN in
|
// This directory is still experimental. Define HAVE_P3D_PLUGIN in
|
||||||
// your Config.pp to build it.
|
// your Config.pp to build it.
|
||||||
#define BUILD_DIRECTORY $[HAVE_P3D_PLUGIN]
|
#define BUILD_DIRECTORY $[and $[HAVE_P3D_PLUGIN],$[HAVE_PYTHON],$[HAVE_TINYXML]]
|
||||||
|
|
||||||
#begin lib_target
|
#begin lib_target
|
||||||
#define USE_PACKAGES tinyxml
|
#define USE_PACKAGES tinyxml
|
||||||
@ -30,13 +30,20 @@
|
|||||||
#end lib_target
|
#end lib_target
|
||||||
|
|
||||||
#begin bin_target
|
#begin bin_target
|
||||||
#define USE_PACKAGES tinyxml
|
#define USE_PACKAGES tinyxml python
|
||||||
#define TARGET p3dpython
|
#define TARGET p3dpython
|
||||||
|
|
||||||
|
#define OTHER_LIBS \
|
||||||
|
dtoolutil:c dtoolbase:c dtool:m \
|
||||||
|
interrogatedb:c dconfig:c dtoolconfig:m \
|
||||||
|
express:c pandaexpress:m \
|
||||||
|
prc:c pstatclient:c pandabase:c linmath:c putil:c \
|
||||||
|
pipeline:c panda:m
|
||||||
|
|
||||||
#define SOURCES \
|
#define SOURCES \
|
||||||
handleStream.cxx handleStream.h handleStream.I \
|
handleStream.cxx handleStream.h handleStream.I \
|
||||||
handleStreamBuf.cxx handleStreamBuf.h \
|
handleStreamBuf.cxx handleStreamBuf.h \
|
||||||
p3d_lock.h \
|
p3d_lock.h p3d_plugin.h \
|
||||||
p3dCInstance.cxx \
|
p3dCInstance.cxx \
|
||||||
p3dCInstance.h p3dCInstance.I \
|
p3dCInstance.h p3dCInstance.I \
|
||||||
p3dPythonRun.cxx p3dPythonRun.h p3dPythonRun.I
|
p3dPythonRun.cxx p3dPythonRun.h p3dPythonRun.I
|
||||||
|
@ -15,9 +15,11 @@
|
|||||||
#ifndef P3DCINSTANCE_H
|
#ifndef P3DCINSTANCE_H
|
||||||
#define P3DCINSTANCE_H
|
#define P3DCINSTANCE_H
|
||||||
|
|
||||||
#include "p3d_plugin.h"
|
#include "pandabase.h"
|
||||||
|
|
||||||
|
#include "p3d_plugin.h"
|
||||||
|
#include "pvector.h"
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <tinyxml.h>
|
#include <tinyxml.h>
|
||||||
|
|
||||||
class P3DSession;
|
class P3DSession;
|
||||||
@ -41,7 +43,7 @@ private:
|
|||||||
string _keyword;
|
string _keyword;
|
||||||
string _value;
|
string _value;
|
||||||
};
|
};
|
||||||
typedef vector<Token> Tokens;
|
typedef pvector<Token> Tokens;
|
||||||
|
|
||||||
P3D_request_ready_func *_func;
|
P3D_request_ready_func *_func;
|
||||||
string _p3d_filename;
|
string _p3d_filename;
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "p3dPythonRun.h"
|
#include "p3dPythonRun.h"
|
||||||
|
#include "asyncTaskManager.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DPythonRun::Constructor
|
// Function: P3DPythonRun::Constructor
|
||||||
@ -114,41 +115,10 @@ run_python() {
|
|||||||
}
|
}
|
||||||
Py_DECREF(appmf);
|
Py_DECREF(appmf);
|
||||||
|
|
||||||
// Construct a Python wrapper around our check_comm() method.
|
// Now add check_comm() as a task.
|
||||||
|
_check_comm_task = new GenericAsyncTask("check_comm", st_check_comm, this);
|
||||||
static PyMethodDef p3dpython_methods[] = {
|
AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr();
|
||||||
{"check_comm", P3DPythonRun::py_check_comm, METH_VARARGS,
|
task_mgr->add(_check_comm_task);
|
||||||
"Check for communications to and from the plugin host."},
|
|
||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
|
||||||
};
|
|
||||||
PyObject *p3dpython = Py_InitModule("p3dpython", p3dpython_methods);
|
|
||||||
if (p3dpython == NULL) {
|
|
||||||
PyErr_Print();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *check_comm = PyObject_GetAttrString(p3dpython, "check_comm");
|
|
||||||
if (check_comm == NULL) {
|
|
||||||
PyErr_Print();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now add check_comm() as a Python task.
|
|
||||||
PyObject *add_check_comm = PyObject_GetAttrString(appmf, "add_check_comm");
|
|
||||||
if (add_check_comm == NULL) {
|
|
||||||
PyErr_Print();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *task = PyObject_CallFunction
|
|
||||||
(add_check_comm, "Ol", check_comm, (long)this);
|
|
||||||
if (task == NULL) {
|
|
||||||
PyErr_Print();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Py_DECREF(task);
|
|
||||||
Py_DECREF(add_check_comm);
|
|
||||||
Py_DECREF(check_comm);
|
|
||||||
|
|
||||||
// Finally, get lost in taskMgr.run().
|
// Finally, get lost in taskMgr.run().
|
||||||
|
|
||||||
@ -212,8 +182,8 @@ handle_command(TiXmlDocument *doc) {
|
|||||||
// from, and requests to be delivered to, the plugin
|
// from, and requests to be delivered to, the plugin
|
||||||
// host in the parent process.
|
// host in the parent process.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void P3DPythonRun::
|
AsyncTask::DoneStatus P3DPythonRun::
|
||||||
check_comm() {
|
check_comm(GenericAsyncTask *task) {
|
||||||
ACQUIRE_LOCK(_commands_lock);
|
ACQUIRE_LOCK(_commands_lock);
|
||||||
while (!_commands.empty()) {
|
while (!_commands.empty()) {
|
||||||
TiXmlDocument *doc = _commands.front();
|
TiXmlDocument *doc = _commands.front();
|
||||||
@ -232,27 +202,21 @@ check_comm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RELEASE_LOCK(_commands_lock);
|
RELEASE_LOCK(_commands_lock);
|
||||||
|
|
||||||
|
return AsyncTask::DS_cont;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DPythonRun::py_check_comm
|
// Function: P3DPythonRun::st_check_comm
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
// Description: This method is added as a Python task function on the
|
// Description: This static function wrapper around check_comm is
|
||||||
// task manager. It is the Python wrapper around the
|
// necessary to add the method function to the
|
||||||
// check_comm method.
|
// GenericAsyncTask object.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PyObject *P3DPythonRun::
|
AsyncTask::DoneStatus P3DPythonRun::
|
||||||
py_check_comm(PyObject *, PyObject *args) {
|
st_check_comm(GenericAsyncTask *task, void *user_data) {
|
||||||
long this_int;
|
P3DPythonRun *self = (P3DPythonRun *)user_data;
|
||||||
PyObject *task;
|
return self->check_comm(task);
|
||||||
if (!PyArg_ParseTuple(args, "lO:check_comm", &this_int, &task)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
P3DPythonRun *self = (P3DPythonRun *)(void *)this_int;
|
|
||||||
self->check_comm();
|
|
||||||
|
|
||||||
return PyObject_GetAttrString(task, "cont");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -266,6 +230,12 @@ void P3DPythonRun::
|
|||||||
spawn_read_thread() {
|
spawn_read_thread() {
|
||||||
assert(!_read_thread_continue);
|
assert(!_read_thread_continue);
|
||||||
|
|
||||||
|
// We have to use direct OS calls to create the thread instead of
|
||||||
|
// Panda constructs, because it has to be an actual thread, not
|
||||||
|
// necessarily a Panda thread (we can't use Panda's simple threads
|
||||||
|
// implementation, because we can't get overlapped I/O on an
|
||||||
|
// anonymous pipe in Windows).
|
||||||
|
|
||||||
_read_thread_continue = true;
|
_read_thread_continue = true;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
_read_thread = CreateThread(NULL, 0, &win_rt_thread_run, this, 0, NULL);
|
_read_thread = CreateThread(NULL, 0, &win_rt_thread_run, this, 0, NULL);
|
||||||
@ -356,8 +326,8 @@ terminate_instance(int id) {
|
|||||||
delete inst;
|
delete inst;
|
||||||
|
|
||||||
// TODO: we don't currently have any way to stop just one instance
|
// TODO: we don't currently have any way to stop just one instance
|
||||||
// of a multi-instance session. We could maybe close its window or
|
// of a multi-instance session. This will require a different
|
||||||
// something.
|
// Python interface than ShowBase.
|
||||||
terminate_session();
|
terminate_session();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,20 +15,22 @@
|
|||||||
#ifndef P3DPYTHONRUN_H
|
#ifndef P3DPYTHONRUN_H
|
||||||
#define P3DPYTHONRUN_H
|
#define P3DPYTHONRUN_H
|
||||||
|
|
||||||
#include <iostream>
|
#include "pandabase.h"
|
||||||
#include <string>
|
|
||||||
#include <deque>
|
#ifdef _WIN32
|
||||||
#include <map>
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <assert.h>
|
#include <windows.h>
|
||||||
#include <Python.h>
|
#endif
|
||||||
#include <tinyxml.h>
|
|
||||||
#include "p3d_lock.h"
|
#include "p3d_lock.h"
|
||||||
#include "handleStream.h"
|
#include "handleStream.h"
|
||||||
#include "p3dCInstance.h"
|
#include "p3dCInstance.h"
|
||||||
|
#include "genericAsyncTask.h"
|
||||||
|
#include "pmap.h"
|
||||||
|
#include "pdeque.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#include <Python.h>
|
||||||
#include <windows.h>
|
#include <tinyxml.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -56,8 +58,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_command(TiXmlDocument *doc);
|
void handle_command(TiXmlDocument *doc);
|
||||||
void check_comm();
|
AsyncTask::DoneStatus check_comm(GenericAsyncTask *task);
|
||||||
static PyObject *py_check_comm(PyObject *, PyObject *args);
|
static AsyncTask::DoneStatus st_check_comm(GenericAsyncTask *task, void *user_data);
|
||||||
|
|
||||||
void spawn_read_thread();
|
void spawn_read_thread();
|
||||||
void join_read_thread();
|
void join_read_thread();
|
||||||
@ -68,13 +70,14 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// This method runs only within the read thread.
|
// This method runs only within the read thread.
|
||||||
|
|
||||||
void rt_thread_run();
|
void rt_thread_run();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static DWORD WINAPI win_rt_thread_run(LPVOID data);
|
static DWORD WINAPI win_rt_thread_run(LPVOID data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef map<int, P3DCInstance *> Instances;
|
typedef pmap<int, P3DCInstance *> Instances;
|
||||||
Instances _instances;
|
Instances _instances;
|
||||||
|
|
||||||
string _program_name;
|
string _program_name;
|
||||||
@ -85,9 +88,15 @@ private:
|
|||||||
PyObject *_exit;
|
PyObject *_exit;
|
||||||
PyObject *_setupWindow;
|
PyObject *_setupWindow;
|
||||||
|
|
||||||
|
PT(GenericAsyncTask) _check_comm_task;
|
||||||
|
|
||||||
// The remaining members are manipulated by the read thread.
|
// The remaining members are manipulated by the read thread.
|
||||||
typedef deque<TiXmlDocument *> Commands;
|
typedef pdeque<TiXmlDocument *> Commands;
|
||||||
Commands _commands;
|
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;
|
LOCK _commands_lock;
|
||||||
|
|
||||||
HandleStream _pipe_read;
|
HandleStream _pipe_read;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user