p3dPythonRun.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Filename: p3dPythonRun.h
  2. // Created by: drose (05Jun09)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #ifndef P3DPYTHONRUN_H
  15. #define P3DPYTHONRUN_H
  16. #include "pandabase.h"
  17. #ifdef _WIN32
  18. #define WIN32_LEAN_AND_MEAN
  19. #include <windows.h>
  20. #endif
  21. #include "p3d_lock.h"
  22. #include "handleStream.h"
  23. #include "p3dCInstance.h"
  24. #include "genericAsyncTask.h"
  25. #include "pmap.h"
  26. #include "pdeque.h"
  27. #include <Python.h>
  28. #include <tinyxml.h>
  29. using namespace std;
  30. ////////////////////////////////////////////////////////////////////
  31. // Class : P3DPythonRun
  32. // Description : This class is used to run, and communicate with,
  33. // embedded Python in a sub-process. It is compiled and
  34. // launched as a separate executable from the p3d_plugin
  35. // dll, because that's the only way Windows can launch a
  36. // sub-process, and also because it makes it possible to
  37. // compile-time link with Panda and Python, instead of
  38. // having to go through the clumsy dynamic-loading
  39. // interface.
  40. //
  41. // Communication is via XML files exchanged via
  42. // anonymous pipes from the parent process. This isn't
  43. // terribly eficient, of course, but it's easy; and it's
  44. // a fairly low-bandwidth channel so efficiency is not
  45. // paramount.
  46. //
  47. // This executable is not designed to stand alone; it is
  48. // designed to be invoked only by p3d_plugin.
  49. ////////////////////////////////////////////////////////////////////
  50. class P3DPythonRun {
  51. public:
  52. P3DPythonRun(int argc, char *argv[]);
  53. ~P3DPythonRun();
  54. bool run_python();
  55. private:
  56. void handle_command(TiXmlDocument *doc);
  57. AsyncTask::DoneStatus check_comm(GenericAsyncTask *task);
  58. static AsyncTask::DoneStatus st_check_comm(GenericAsyncTask *task, void *user_data);
  59. void spawn_read_thread();
  60. void join_read_thread();
  61. void start_instance(P3DCInstance *inst);
  62. void terminate_instance(int id);
  63. void terminate_session();
  64. private:
  65. // This method runs only within the read thread.
  66. void rt_thread_run();
  67. #ifdef _WIN32
  68. static DWORD WINAPI win_rt_thread_run(LPVOID data);
  69. #endif
  70. private:
  71. typedef pmap<int, P3DCInstance *> Instances;
  72. Instances _instances;
  73. string _program_name;
  74. int _py_argc;
  75. char **_py_argv;
  76. PyObject *_runPackedApp;
  77. PyObject *_setupWindow;
  78. PyObject *_taskMgr;
  79. PT(GenericAsyncTask) _check_comm_task;
  80. // The remaining members are manipulated by the read thread.
  81. typedef pdeque<TiXmlDocument *> Commands;
  82. Commands _commands;
  83. // This has to be an actual OS LOCK instead of Panda's Mutex,
  84. // because we have to use a true thread here, not one of Panda's
  85. // simple threads.
  86. LOCK _commands_lock;
  87. HandleStream _pipe_read;
  88. HandleStream _pipe_write;
  89. bool _read_thread_continue;
  90. bool _program_continue;
  91. #ifdef _WIN32
  92. HANDLE _read_thread;
  93. #endif
  94. };
  95. #include "p3dPythonRun.I"
  96. #endif