separate out p3dpython.exe and libp3dpython.dll

This commit is contained in:
David Rose 2009-08-31 22:25:32 +00:00
parent 06fa43a83b
commit 1415193b5e
3 changed files with 67 additions and 202 deletions

View File

@ -93,10 +93,18 @@
#end lib_target
#begin lib_target
// *****
// Note! This lib is used to run P3DPythonRun within the parent
// (browser) process, instead of forking a child. This seems like
// it's going to be a bad idea in the long term. This lib remains
// for now as an experiment, but it will likely be removed very soon.
// ****
#define BUILD_TARGET $[HAVE_PYTHON]
#define USE_PACKAGES tinyxml python
#define TARGET p3dpython
#define TARGET libp3dpython
#define LIB_PREFIX
#define OTHER_LIBS \
dtoolutil:c dtoolbase:c dtool:m \
@ -122,12 +130,35 @@
#begin bin_target
#define BUILD_TARGET $[HAVE_PYTHON]
#define USE_PACKAGES tinyxml python
#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 event:c nativenet:c net:c panda:m
#define SOURCES \
binaryXml.cxx binaryXml.h \
fhandle.h \
p3dPythonMain.cxx \
run_p3dpython.h
handleStream.cxx handleStream.h handleStream.I \
handleStreamBuf.cxx handleStreamBuf.h handleStreamBuf.I \
p3d_lock.h p3d_plugin.h \
p3d_plugin_config.h \
p3dCInstance.cxx \
p3dCInstance.h p3dCInstance.I \
p3dPythonRun.cxx p3dPythonRun.h p3dPythonRun.I \
run_p3dpython.h run_p3dpython.cxx
#define SOURCES $[SOURCES] \
p3dPythonMain.cxx
// If you have to link with a static Python library, define it here.
#define EXTRA_LIBS $[EXTRA_P3DPYTHON_LIBS]
#define WIN_SYS_LIBS user32.lib
#end bin_target
#begin static_lib_target

View File

@ -19,29 +19,16 @@
#include <string.h> // strrchr
using namespace std;
#ifndef _WIN32
#include <dlfcn.h>
#endif
#ifdef _WIN32
static const string dll_ext = ".dll";
#elif defined(__APPLE__)
static const string dll_ext = ".dylib";
#else
static const string dll_ext = ".so";
#endif
////////////////////////////////////////////////////////////////////
// Function: main
// Description: This is a trivial main() function that loads and runs
// libp3dpython.dll. It's used to build p3dpython.exe,
// Description: This is a trivial main() function that invokes
// P3DPythonRun. It's used to build p3dpython.exe,
// which is the preferred way to run Python in a child
// process, as a separate executable.
////////////////////////////////////////////////////////////////////
int
main(int argc, char *argv[]) {
const char *program_name = argv[0];
const char *dll_file = NULL;
const char *archive_file = NULL;
const char *input_handle_str = NULL;
const char *output_handle_str = NULL;
@ -49,27 +36,19 @@ main(int argc, char *argv[]) {
const char *interactive_console_str = NULL;
if (argc > 1) {
dll_file = argv[1];
archive_file = argv[1];
}
if (argc > 2) {
archive_file = argv[2];
input_handle_str = argv[2];
}
if (argc > 3) {
input_handle_str = argv[3];
output_handle_str = argv[3];
}
if (argc > 4) {
output_handle_str = argv[4];
error_handle_str = argv[4];
}
if (argc > 5) {
error_handle_str = argv[5];
}
if (argc > 6) {
interactive_console_str = argv[6];
}
if (dll_file == NULL || *dll_file == '\0') {
cerr << "No libp3dpython filename specified on command line.\n";
return 1;
interactive_console_str = argv[5];
}
if (archive_file == NULL || *archive_file == '\0') {
@ -118,121 +97,6 @@ main(int argc, char *argv[]) {
<< ", " << error_handle << "\n";
cerr << "interactive_console = " << interactive_console << "\n";
// For some vague idea of security, we insist that this program can
// only run libp3dpython.dll: you can't use it to load just any
// arbitrary DLL on the system. Of course, if you're successfully
// running this program in the first place, you probably don't need
// any help to load an arbitrary DLL, but whatever.
// Find the basename of the dll_file.
const char *slash = strrchr(dll_file, '/');
#ifdef _WIN32
const char *backslash = strrchr(dll_file, '\\');
if (backslash != NULL && (slash == NULL || backslash > slash)) {
slash = backslash;
}
#endif
string basename;
if (slash == NULL) {
basename = dll_file;
} else {
//dirname = string(dll_file, slash - dll_file);
basename = (slash + 1);
}
string expected_basename = "libp3dpython" + dll_ext;
if (basename != expected_basename) {
cerr << dll_file << " does not name " << expected_basename << "\n";
return 1;
}
// Everything checks out. Load and run the library.
#ifdef _WIN32
SetErrorMode(0);
HMODULE module = LoadLibrary(dll_file);
if (module == NULL) {
// Couldn't load the DLL.
cerr << "Couldn't load " << dll_file << "\n";
return 1;
}
#define get_func GetProcAddress
// Get the default values for the communication handles, if we
// weren't given specific handles.
if (input_handle == invalid_fhandle) {
input_handle = GetStdHandle(STD_INPUT_HANDLE);
// Close the system input handle, so application code won't
// accidentally read from our private input stream.
if (!SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE)) {
cerr << "unable to reset input handle\n";
}
}
if (output_handle == invalid_fhandle) {
output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
// Close the system output handle, so application code won't
// accidentally write to our private output stream.
if (!SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE)) {
cerr << "unable to reset input handle\n";
}
}
// No matter what error handle we were given, make it
// STD_ERROR_HANDLE.
if (error_handle == invalid_fhandle) {
error_handle = GetStdHandle(STD_ERROR_HANDLE);
} else {
SetStdHandle(STD_ERROR_HANDLE, error_handle);
}
#else // _WIN32
// Posix case.
void *module = dlopen(dll_file, RTLD_LAZY | RTLD_LOCAL);
if (module == NULL) {
// Couldn't load the .so.
cerr << "Couldn't load " << dll_file << "\n";
char *message = dlerror();
if (message != (char *)NULL) {
cerr << message << "\n";
} else {
cerr << "No error.\n";
}
return 1;
}
#define get_func dlsym
// Get the default values for the communication handles, if we
// weren't given specific handles.
if (input_handle == invalid_fhandle) {
input_handle = STDIN_FILENO;
}
if (output_handle == invalid_fhandle) {
output_handle = STDOUT_FILENO;
}
// No matter what error handle we were given, make it STDERR_FILENO.
if (error_handle == invalid_fhandle) {
error_handle = STDERR_FILENO;
} else if (error_handle != STDERR_FILENO) {
dup2(error_handle, STDERR_FILENO);
close(error_handle);
error_handle = STDERR_FILENO;
}
#endif // _WIN32
run_p3dpython_func *run_p3dpython = (run_p3dpython_func *)get_func(module, "run_p3dpython");
if (run_p3dpython == NULL) {
cerr << "Couldn't find run_p3dpython\n";
return 1;
}
if (!run_p3dpython(program_name, archive_file, input_handle, output_handle,
error_handle, interactive_console)) {
cerr << "Failure on startup.\n";

View File

@ -747,51 +747,16 @@ start_p3dpython(P3DInstance *inst) {
<< "PRC_PATH set to: " << prc_path << "\n";
}
// Get the name of the executable and dynamic library to run.
// Ideally, we'll run the executable successfully, in a sub-process;
// this will in turn load and run the dynamic library. If that
// fails for some reason, we can fall back to loading and running
// the library directly.
_p3dpython_exe = _python_root_dir + "/p3dpython";
// Get the name of the executable to run. Ideally, we'll run the
// executable successfully, in a sub-process; this will in turn load
// and run the dynamic library. If that fails for some reason, we
// can fall back to loading and running the library directly.
_p3dpython_exe = P3D_PLUGIN_P3DPYTHON;
if (_p3dpython_exe.empty()) {
_p3dpython_exe = _python_root_dir + "/p3dpython";
#ifdef _WIN32
_p3dpython_exe += ".exe";
_p3dpython_exe += ".exe";
#endif
_p3dpython_dll = P3D_PLUGIN_P3DPYTHON;
if (_p3dpython_dll.empty()) {
_p3dpython_dll = _python_root_dir + "/libp3dpython";
#ifdef _WIN32
_p3dpython_dll += ".dll";
#elif defined(__APPLE__)
_p3dpython_dll += ".dylib";
#else
_p3dpython_dll += ".so";
#endif
} else {
// We have a custom path to libp3dpython.dylib etc., for
// development.
#ifdef __APPLE__
// For some bizarre reason, Apple's dlopen() goes out of its way to
// ignore whatever full path you specify, and always searches for
// the file's basename along $DYLD_LIBRARY_PATH. Weird. To work
// around this and load the full path we're actually asking for, we
// have to ensure that our desired path appears first on
// $DYLD_LIBRARY_PATH.
// This may also inadvertently put other (incorrect) files first
// on the path, but presumably this won't cause too much trouble,
// since the user is in development mode anyway and maybe won't
// mind.
size_t slash = _p3dpython_dll.rfind('/');
if (slash != string::npos) {
string dirname = _p3dpython_dll.substr(0, slash);
cerr << "dirname is " << dirname << "\n";
dyld_path = dirname + ":" + dyld_path;
cerr << "dyld_path is " << dyld_path << "\n";
}
#endif // __APPLE__
}
// Populate the new process' environment.
@ -998,8 +963,7 @@ start_p3dpython(P3DInstance *inst) {
// to p3dpython.
_mf_filename = inst->_panda3d->get_archive_file_pathname();
nout << "Attempting to start python from " << _p3dpython_exe
<< " and " << _p3dpython_dll << "\n";
nout << "Attempting to start python from " << _p3dpython_exe << "\n";
bool started_p3dpython;
if (one_process) {
@ -1225,10 +1189,10 @@ win_create_process() {
// Construct the command-line string, containing the quoted
// command-line arguments.
ostringstream stream;
stream << "\"" << _p3dpython_exe << "\" \"" << _p3dpython_dll
<< "\" \"" << _mf_filename << "\" \"" << _input_handle
<< "\" \"" << _output_handle << "\" \"" << _error_handle
<< "\" \"" << _interactive_console << "\"";
stream << "\"" << _p3dpython_exe << "\" \"" << _mf_filename
<< "\" \"" << _input_handle << "\" \"" << _output_handle
<< "\" \"" << _error_handle << "\" \"" << _interactive_console
<< "\"";
// I'm not sure why CreateProcess wants a non-const char pointer for
// its command-line string, but I'm not taking chances. It gets a
@ -1330,8 +1294,7 @@ posix_create_process() {
error_handle_stream << _error_handle;
string error_handle_str = error_handle_stream.str();
execle(_p3dpython_exe.c_str(),
_p3dpython_exe.c_str(), _p3dpython_dll.c_str(),
execle(_p3dpython_exe.c_str(), _p3dpython_exe.c_str(),
_mf_filename.c_str(), input_handle_str.c_str(),
output_handle_str.c_str(), error_handle_str.c_str(),
_interactive_console ? "1" : "0", (char *)0, &ptrs[0]);
@ -1386,12 +1349,14 @@ p3dpython_thread_run() {
}
// Now load the library.
string libp3dpython = _python_root_dir + "/libp3dpython";
#ifdef _WIN32
libp3dpython += ".dll";
SetErrorMode(0);
HMODULE module = LoadLibrary(_p3dpython_dll.c_str());
HMODULE module = LoadLibrary(libp3dpython.c_str());
if (module == NULL) {
// Couldn't load the DLL.
nout << "Couldn't load " << _p3dpython_dll << "\n";
nout << "Couldn't load " << libp3dpython << "\n";
return;
}
@ -1399,10 +1364,15 @@ p3dpython_thread_run() {
#else // _WIN32
// Posix case.
void *module = dlopen(_p3dpython_dll.c_str(), RTLD_LAZY | RTLD_LOCAL);
#ifdef __APPLE__
libp3dpython += ".dylib";
#else
libp3dpython += ".so";
#endif
void *module = dlopen(libp3dpython.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (module == NULL) {
// Couldn't load the .so.
nout << "Couldn't load " << _p3dpython_dll << "\n";
nout << "Couldn't load " << libp3dpython << "\n";
return;
}
@ -1416,7 +1386,7 @@ p3dpython_thread_run() {
return;
}
if (!run_p3dpython(_p3dpython_dll.c_str(), _mf_filename.c_str(),
if (!run_p3dpython(libp3dpython.c_str(), _mf_filename.c_str(),
_input_handle, _output_handle, _error_handle,
_interactive_console)) {
nout << "Failure on startup.\n";