p3dPythonMain.cxx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Filename: p3dPythonMain.cxx
  2. // Created by: drose (29Aug09)
  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. #include "run_p3dpython.h"
  15. #include <iostream>
  16. #include <sstream>
  17. #include <string.h> // strrchr
  18. using namespace std;
  19. #ifndef _WIN32
  20. #include <dlfcn.h>
  21. #endif
  22. #ifdef _WIN32
  23. static const string dll_ext = ".dll";
  24. #elif defined(__APPLE__)
  25. static const string dll_ext = ".dylib";
  26. #else
  27. static const string dll_ext = ".so";
  28. #endif
  29. ////////////////////////////////////////////////////////////////////
  30. // Function: main
  31. // Description: This is a trivial main() function that loads and runs
  32. // libp3dpython.dll. It's used to build p3dpython.exe,
  33. // which is the preferred way to run Python in a child
  34. // process, as a separate executable.
  35. ////////////////////////////////////////////////////////////////////
  36. int
  37. main(int argc, char *argv[]) {
  38. const char *program_name = argv[0];
  39. const char *dll_file = NULL;
  40. const char *archive_file = NULL;
  41. const char *input_handle_str = NULL;
  42. const char *output_handle_str = NULL;
  43. const char *error_handle_str = NULL;
  44. const char *interactive_console_str = NULL;
  45. if (argc > 1) {
  46. dll_file = argv[1];
  47. }
  48. if (argc > 2) {
  49. archive_file = argv[2];
  50. }
  51. if (argc > 3) {
  52. input_handle_str = argv[3];
  53. }
  54. if (argc > 4) {
  55. output_handle_str = argv[4];
  56. }
  57. if (argc > 5) {
  58. error_handle_str = argv[5];
  59. }
  60. if (argc > 6) {
  61. interactive_console_str = argv[6];
  62. }
  63. if (dll_file == NULL || *dll_file == '\0') {
  64. cerr << "No libp3dpython filename specified on command line.\n";
  65. return 1;
  66. }
  67. if (archive_file == NULL || *archive_file == '\0') {
  68. cerr << "No archive filename specified on command line.\n";
  69. return 1;
  70. }
  71. FHandle input_handle = invalid_fhandle;
  72. if (input_handle_str != NULL && *input_handle_str) {
  73. stringstream stream(input_handle_str);
  74. stream >> input_handle;
  75. if (!stream) {
  76. input_handle = invalid_fhandle;
  77. }
  78. }
  79. FHandle output_handle = invalid_fhandle;
  80. if (output_handle_str != NULL && *output_handle_str) {
  81. stringstream stream(output_handle_str);
  82. stream >> output_handle;
  83. if (!stream) {
  84. output_handle = invalid_fhandle;
  85. }
  86. }
  87. FHandle error_handle = invalid_fhandle;
  88. if (error_handle_str != NULL && *error_handle_str) {
  89. stringstream stream(error_handle_str);
  90. stream >> error_handle;
  91. if (!stream) {
  92. error_handle = invalid_fhandle;
  93. }
  94. }
  95. bool interactive_console = false;
  96. if (interactive_console_str != NULL && *interactive_console_str) {
  97. stringstream stream(interactive_console_str);
  98. int flag;
  99. stream >> flag;
  100. if (stream) {
  101. interactive_console = (flag != 0);
  102. }
  103. }
  104. cerr << "handles: " << input_handle << ", " << output_handle
  105. << ", " << error_handle << "\n";
  106. cerr << "interactive_console = " << interactive_console << "\n";
  107. // For some vague idea of security, we insist that this program can
  108. // only run libp3dpython.dll: you can't use it to load just any
  109. // arbitrary DLL on the system. Of course, if you're successfully
  110. // running this program in the first place, you probably don't need
  111. // any help to load an arbitrary DLL, but whatever.
  112. // Find the basename of the dll_file.
  113. const char *slash = strrchr(dll_file, '/');
  114. #ifdef _WIN32
  115. const char *backslash = strrchr(dll_file, '\\');
  116. if (backslash != NULL && (slash == NULL || backslash > slash)) {
  117. slash = backslash;
  118. }
  119. #endif
  120. string basename;
  121. if (slash == NULL) {
  122. basename = dll_file;
  123. } else {
  124. //dirname = string(dll_file, slash - dll_file);
  125. basename = (slash + 1);
  126. }
  127. string expected_basename = "libp3dpython" + dll_ext;
  128. if (basename != expected_basename) {
  129. cerr << dll_file << " does not name " << expected_basename << "\n";
  130. return 1;
  131. }
  132. // Everything checks out. Load and run the library.
  133. #ifdef _WIN32
  134. SetErrorMode(0);
  135. HMODULE module = LoadLibrary(dll_file);
  136. if (module == NULL) {
  137. // Couldn't load the DLL.
  138. cerr << "Couldn't load " << dll_file << "\n";
  139. return 1;
  140. }
  141. #define get_func GetProcAddress
  142. // Get the default values for the communication handles, if we
  143. // weren't given specific handles.
  144. if (input_handle == invalid_fhandle) {
  145. input_handle = GetStdHandle(STD_INPUT_HANDLE);
  146. // Close the system input handle, so application code won't
  147. // accidentally read from our private input stream.
  148. if (!SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE)) {
  149. cerr << "unable to reset input handle\n";
  150. }
  151. }
  152. if (output_handle == invalid_fhandle) {
  153. output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
  154. // Close the system output handle, so application code won't
  155. // accidentally write to our private output stream.
  156. if (!SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE)) {
  157. cerr << "unable to reset input handle\n";
  158. }
  159. }
  160. // No matter what error handle we were given, make it
  161. // STD_ERROR_HANDLE.
  162. if (error_handle == invalid_fhandle) {
  163. error_handle = GetStdHandle(STD_ERROR_HANDLE);
  164. } else {
  165. SetStdHandle(STD_ERROR_HANDLE, error_handle);
  166. }
  167. #else // _WIN32
  168. // Posix case.
  169. void *module = dlopen(dll_file, RTLD_LAZY | RTLD_LOCAL);
  170. if (module == NULL) {
  171. // Couldn't load the .so.
  172. cerr << "Couldn't load " << dll_file << "\n";
  173. char *message = dlerror();
  174. if (message != (char *)NULL) {
  175. cerr << message << "\n";
  176. } else {
  177. cerr << "No error.\n";
  178. }
  179. return 1;
  180. }
  181. #define get_func dlsym
  182. // Get the default values for the communication handles, if we
  183. // weren't given specific handles.
  184. if (input_handle == invalid_fhandle) {
  185. input_handle = STDIN_FILENO;
  186. }
  187. if (output_handle == invalid_fhandle) {
  188. output_handle = STDOUT_FILENO;
  189. }
  190. // No matter what error handle we were given, make it STDERR_FILENO.
  191. if (error_handle == invalid_fhandle) {
  192. error_handle = STDERR_FILENO;
  193. } else if (error_handle != STDERR_FILENO) {
  194. dup2(error_handle, STDERR_FILENO);
  195. close(error_handle);
  196. error_handle = STDERR_FILENO;
  197. }
  198. #endif // _WIN32
  199. run_p3dpython_func *run_p3dpython = (run_p3dpython_func *)get_func(module, "run_p3dpython");
  200. if (run_p3dpython == NULL) {
  201. cerr << "Couldn't find run_p3dpython\n";
  202. return 1;
  203. }
  204. if (!run_p3dpython(program_name, archive_file, input_handle, output_handle,
  205. error_handle, interactive_console)) {
  206. cerr << "Failure on startup.\n";
  207. return 1;
  208. }
  209. return 0;
  210. }