Browse Source

make p3dembed work on linux

David Rose 16 years ago
parent
commit
a15108cbc5

+ 34 - 6
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;

+ 7 - 0
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();
 

+ 1 - 1
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

+ 52 - 27
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 <stdint.h>
-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);
-}
-

+ 2 - 0
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

+ 29 - 0
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 <stdint.h>
+volatile uint32_t p3d_offset = 0xFF3D3D00;
+#endif
+
+int
+main(int argc, char *argv[]) {
+  P3DEmbed program(true);
+  return program.run_embedded(p3d_offset, argc, argv);
+}
+