Browse Source

p3dpython can be a Panda app

David Rose 16 years ago
parent
commit
b660d0f3e5

+ 10 - 3
direct/src/plugin/Sources.pp

@@ -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

+ 4 - 2
direct/src/plugin/p3dCInstance.h

@@ -15,9 +15,11 @@
 #ifndef P3DCINSTANCE_H
 #ifndef P3DCINSTANCE_H
 #define P3DCINSTANCE_H
 #define P3DCINSTANCE_H
 
 
+#include "pandabase.h"
+
 #include "p3d_plugin.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;

+ 25 - 55
direct/src/plugin/p3dPythonRun.cxx

@@ -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.
-
-  static PyMethodDef p3dpython_methods[] = {
-    {"check_comm", P3DPythonRun::py_check_comm, METH_VARARGS,
-     "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);
+  // Now add check_comm() as a task.
+  _check_comm_task = new GenericAsyncTask("check_comm", st_check_comm, this);
+  AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr();
+  task_mgr->add(_check_comm_task);
 
 
   // 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::
-check_comm() {
+AsyncTask::DoneStatus P3DPythonRun::
+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
-//               task manager.  It is the Python wrapper around the
-//               check_comm method.
+//  Description: This static function wrapper around check_comm is
+//               necessary to add the method function to the
+//               GenericAsyncTask object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-PyObject *P3DPythonRun::
-py_check_comm(PyObject *, PyObject *args) {
-  long this_int;
-  PyObject *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");
+AsyncTask::DoneStatus P3DPythonRun::
+st_check_comm(GenericAsyncTask *task, void *user_data) {
+  P3DPythonRun *self = (P3DPythonRun *)user_data;
+  return self->check_comm(task);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -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
-  // something.
+  // of a multi-instance session.  This will require a different
+  // Python interface than ShowBase.
   terminate_session();
   terminate_session();
 }
 }
 
 

+ 23 - 14
direct/src/plugin/p3dPythonRun.h

@@ -15,21 +15,23 @@
 #ifndef P3DPYTHONRUN_H
 #ifndef P3DPYTHONRUN_H
 #define P3DPYTHONRUN_H
 #define P3DPYTHONRUN_H
 
 
-#include <iostream>
-#include <string>
-#include <deque>
-#include <map>
-#include <assert.h>
-#include <Python.h>
-#include <tinyxml.h>
-#include "p3d_lock.h"
-#include "handleStream.h"
-#include "p3dCInstance.h"
+#include "pandabase.h"
 
 
 #ifdef _WIN32
 #ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <windows.h>
 #endif
 #endif
 
 
+#include "p3d_lock.h"
+#include "handleStream.h"
+#include "p3dCInstance.h"
+#include "genericAsyncTask.h"
+#include "pmap.h"
+#include "pdeque.h"
+
+#include <Python.h>
+#include <tinyxml.h>
+
 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();
-  static PyObject *py_check_comm(PyObject *, PyObject *args);
+  AsyncTask::DoneStatus check_comm(GenericAsyncTask *task);
+  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;