diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index 34741a6343..c80d3f8471 100755 --- a/direct/src/plugin/load_plugin.cxx +++ b/direct/src/plugin/load_plugin.cxx @@ -185,7 +185,7 @@ load_plugin(const string &p3d_plugin_filename, // Posix case. assert(module == NULL); if (filename.empty()) { - module = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); + module = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL | RTLD_DEEPBIND); } else { module = dlopen(filename.c_str(), RTLD_LAZY | RTLD_LOCAL); } @@ -247,6 +247,38 @@ load_plugin(const string &p3d_plugin_filename, #undef get_func + // Successfully loaded. + plugin_loaded = true; + + if (!init_plugin(contents_filename, host_url, + verify_contents, platform, + log_directory, log_basename, + trusted_environment, console_environment, + root_dir, logfile)) { + unload_dso(); + return false; + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: init_plugin +// Description: Ensures all the required function pointers have been +// set, and then calls P3D_initialize() on the +// recently-loaded plugin. Returns true on success, +// false on failure. +// +// It is not necessary to call this after calling +// load_plugin(); it is called implicitly. +//////////////////////////////////////////////////////////////////// +bool +init_plugin(const string &contents_filename, const string &host_url, + bool verify_contents, const string &platform, + const string &log_directory, const string &log_basename, + bool trusted_environment, bool console_environment, + const string &root_dir, ostream &logfile) { + // Ensure that all of the function pointers have been found. if (P3D_initialize_ptr == NULL || P3D_finalize_ptr == NULL || @@ -330,13 +362,9 @@ load_plugin(const string &p3d_plugin_filename, << "\nP3D_instance_feed_url_stream_ptr = " << P3D_instance_feed_url_stream_ptr << "\nP3D_instance_handle_event_ptr = " << P3D_instance_handle_event_ptr << "\n"; - unload_dso(); return false; } - // Successfully loaded. - plugin_loaded = true; - if (!P3D_initialize_ptr(P3D_API_VERSION, contents_filename.c_str(), host_url.c_str(), verify_contents, platform.c_str(), log_directory.c_str(), log_basename.c_str(), @@ -346,7 +374,6 @@ load_plugin(const string &p3d_plugin_filename, logfile << "Failed to initialize plugin (passed API version " << P3D_API_VERSION << ")\n"; - unload_plugin(); return false; } @@ -388,6 +415,7 @@ unload_dso() { dlclose(module); #endif module = NULL; + dso_needs_unload = false; } P3D_initialize_ptr = NULL; diff --git a/direct/src/plugin/load_plugin.h b/direct/src/plugin/load_plugin.h index d840753505..bb9b1fa47d 100755 --- a/direct/src/plugin/load_plugin.h +++ b/direct/src/plugin/load_plugin.h @@ -68,6 +68,13 @@ load_plugin(const string &p3d_plugin_filename, const string &log_directory, const string &log_basename, bool trusted_environment, bool console_environment, const string &root_dir, ostream &logfile); +bool +init_plugin(const string &contents_filename, const string &host_url, + bool verify_contents, const string &platform, + const string &log_directory, const string &log_basename, + bool trusted_environment, bool console_environment, + const string &root_dir, ostream &logfile); + void unload_plugin(); bool is_plugin_loaded(); diff --git a/direct/src/plugin_standalone/Sources.pp b/direct/src/plugin_standalone/Sources.pp index de07ee73fd..c66d5b844e 100644 --- a/direct/src/plugin_standalone/Sources.pp +++ b/direct/src/plugin_standalone/Sources.pp @@ -103,7 +103,7 @@ #define SOURCES \ panda3dBase.cxx panda3dBase.h panda3dBase.I \ - p3dEmbed.cxx + p3dEmbed.cxx p3dEmbedMain.cxx #define WIN_RESOURCE_FILE panda3d.rc #define WIN_SYS_LIBS user32.lib gdi32.lib shell32.lib comctl32.lib msimg32.lib ole32.lib diff --git a/direct/src/plugin_standalone/p3dEmbed.cxx b/direct/src/plugin_standalone/p3dEmbed.cxx index 9e69830003..f29d29b4e5 100644 --- a/direct/src/plugin_standalone/p3dEmbed.cxx +++ b/direct/src/plugin_standalone/p3dEmbed.cxx @@ -17,13 +17,6 @@ #include "p3dEmbed.h" #include "load_plugin.h" -#ifdef _WIN32 -volatile unsigned long p3d_offset = 0xFF3D3D00; -#else -#include -volatile uint32_t p3d_offset = 0xFF3D3D00; -#endif - //////////////////////////////////////////////////////////////////// // Function: P3DEmbed::Constructor // Access: Public @@ -46,7 +39,12 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { // value than the one we compiled in, above. We test against // read_offset + 1, because any appearances of this exact number // within the binary will be replaced (including this one). - if (read_offset + (streampos)1 == (streampos)0xFF3D3D01) { + + // We also have to store this computation in a member variable, to + // work around a compiler optimization that might otherwise remove + // the + 1 from the test. + _read_offset_check = read_offset + (streampos)1; + if (_read_offset_check == (streampos)0xFF3D3D01) { cerr << "This program is not intended to be run directly.\nIt is used by pdeploy to construct an embedded Panda3D application.\n"; return 1; } @@ -133,12 +131,52 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { Filename root_dir_f(root_dir); root_dir_f.make_absolute(f.get_dirname()); - // Initialize the plugin. Since we are linked with the core API - // statically, we pass the empty string as the plugin filename, and - // pull the required symbols out of the local address space. - if (!load_plugin("", "", - _host_url, _verify_contents, _this_platform, _log_dirname, - _log_basename, true, _console_environment, + // Initialize the core API by directly assigning all of the function + // pointers. + P3D_initialize_ptr = &P3D_initialize; + P3D_finalize_ptr = &P3D_finalize; + P3D_set_plugin_version_ptr = &P3D_set_plugin_version; + P3D_set_super_mirror_ptr = &P3D_set_super_mirror; + P3D_new_instance_ptr = &P3D_new_instance; + P3D_instance_start_ptr = &P3D_instance_start; + P3D_instance_start_stream_ptr = &P3D_instance_start_stream; + P3D_instance_finish_ptr = &P3D_instance_finish; + P3D_instance_setup_window_ptr = &P3D_instance_setup_window; + + P3D_object_get_type_ptr = &P3D_object_get_type; + P3D_object_get_bool_ptr = &P3D_object_get_bool; + P3D_object_get_int_ptr = &P3D_object_get_int; + P3D_object_get_float_ptr = &P3D_object_get_float; + P3D_object_get_string_ptr = &P3D_object_get_string; + P3D_object_get_repr_ptr = &P3D_object_get_repr; + P3D_object_get_property_ptr = &P3D_object_get_property; + P3D_object_set_property_ptr = &P3D_object_set_property; + P3D_object_has_method_ptr = &P3D_object_has_method; + P3D_object_call_ptr = &P3D_object_call; + P3D_object_eval_ptr = &P3D_object_eval; + P3D_object_incref_ptr = &P3D_object_incref; + P3D_object_decref_ptr = &P3D_object_decref; + + P3D_make_class_definition_ptr = &P3D_make_class_definition; + P3D_new_undefined_object_ptr = &P3D_new_undefined_object; + P3D_new_none_object_ptr = &P3D_new_none_object; + P3D_new_bool_object_ptr = &P3D_new_bool_object; + P3D_new_int_object_ptr = &P3D_new_int_object; + P3D_new_float_object_ptr = &P3D_new_float_object; + P3D_new_string_object_ptr = &P3D_new_string_object; + P3D_instance_get_panda_script_object_ptr = &P3D_instance_get_panda_script_object; + P3D_instance_set_browser_script_object_ptr = &P3D_instance_set_browser_script_object; + + P3D_instance_get_request_ptr = &P3D_instance_get_request; + P3D_check_request_ptr = &P3D_check_request; + P3D_request_finish_ptr = &P3D_request_finish; + P3D_instance_feed_url_stream_ptr = &P3D_instance_feed_url_stream; + P3D_instance_handle_event_ptr = &P3D_instance_handle_event; + + // Now call init_plugin() to verify that we got all of the required + // function pointers. This will also call P3D_initialize(). + if (!init_plugin("", _host_url, _verify_contents, _this_platform, + _log_dirname, _log_basename, true, _console_environment, root_dir_f.to_os_specific(), cerr)) { cerr << "Unable to launch core API\n"; return 1; @@ -152,20 +190,7 @@ run_embedded(streampos read_offset, int argc, char *argv[]) { run_main_loop(); - // Though it's not strictly necessary to call P3D_finalize() here - // (because unload_plugin() will call it), we have to do it anyway, - // to force the contents of libp3d_plugin_static.lib to be linked - // in. If we don't appear to make any calls to these functions, - // then the linker may decide to omit all of them. - P3D_finalize(); unload_plugin(); return 0; } - -int -main(int argc, char *argv[]) { - P3DEmbed program(true); - return program.run_embedded(p3d_offset, argc, argv); -} - diff --git a/direct/src/plugin_standalone/p3dEmbed.h b/direct/src/plugin_standalone/p3dEmbed.h index f93142aac7..6b5ff1f29d 100755 --- a/direct/src/plugin_standalone/p3dEmbed.h +++ b/direct/src/plugin_standalone/p3dEmbed.h @@ -33,6 +33,8 @@ public: P3DEmbed(bool console_environment); int run_embedded(streampos read_offset, int argc, char *argv[]); + + streampos _read_offset_check; }; #endif diff --git a/direct/src/plugin_standalone/p3dEmbedMain.cxx b/direct/src/plugin_standalone/p3dEmbedMain.cxx new file mode 100644 index 0000000000..00360d7f88 --- /dev/null +++ b/direct/src/plugin_standalone/p3dEmbedMain.cxx @@ -0,0 +1,29 @@ +// Filename: p3dEmbedMain.cxx +// Created by: drose (04Jan10) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "p3dEmbed.h" + +#ifdef _WIN32 +volatile unsigned long p3d_offset = 0xFF3D3D00; +#else +#include +volatile uint32_t p3d_offset = 0xFF3D3D00; +#endif + +int +main(int argc, char *argv[]) { + P3DEmbed program(true); + return program.run_embedded(p3d_offset, argc, argv); +} +