Panda3D
load_dso.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file load_dso.cxx
10  * @author drose
11  * @date 2000-05-12
12  */
13 
14 #include "load_dso.h"
15 #include "executionEnvironment.h"
16 
17 using std::string;
18 
19 static Filename resolve_dso(const DSearchPath &path, const Filename &filename) {
20  if (filename.is_local()) {
21  if ((path.get_num_directories()==1)&&(path.get_directory(0)=="<auto>")) {
22  // This is a special case, meaning to search in the same directory in
23  // which libp3dtool.dll, or the exe, was started from.
25  DSearchPath spath(dtoolpath.get_dirname());
26  return spath.find_file(filename);
27  } else {
28  return path.find_file(filename);
29  }
30  } else {
31  return filename;
32  }
33 }
34 
35 #if defined(WIN32)
36 /* begin Win32-specific code */
37 
38 #define WINDOWS_LEAN_AND_MEAN
39 #include <windows.h>
40 #undef WINDOWS_LEAN_AND_MEAN
41 
42 // Loads in a dynamic library like an .so or .dll. Returns NULL if failure,
43 // otherwise on success. If the filename is not absolute, searches the path.
44 // If the path is empty, searches the dtool directory.
45 
46 void *
47 load_dso(const DSearchPath &path, const Filename &filename) {
48  Filename abspath = resolve_dso(path, filename);
49  if (!abspath.is_regular_file()) {
50  return nullptr;
51  }
52  std::wstring os_specific_w = abspath.to_os_specific_w();
53 
54  // Try using LoadLibraryEx, if possible.
55  typedef HMODULE (WINAPI *tLoadLibraryEx)(LPCWSTR, HANDLE, DWORD);
56  tLoadLibraryEx pLoadLibraryEx;
57  HINSTANCE hLib = LoadLibrary("kernel32.dll");
58  if (hLib) {
59  pLoadLibraryEx = (tLoadLibraryEx)GetProcAddress(hLib, "LoadLibraryExW");
60  if (pLoadLibraryEx) {
61  return pLoadLibraryEx(os_specific_w.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
62  }
63  }
64 
65  return LoadLibraryW(os_specific_w.c_str());
66 }
67 
68 bool
69 unload_dso(void *dso_handle) {
70  HMODULE dll_handle = (HMODULE) dso_handle;
71 
72  // true indicates success
73  return (FreeLibrary(dll_handle)!=0);
74 }
75 
76 string
77 load_dso_error() {
78  DWORD last_error = GetLastError();
79 
80  /*
81  LPVOID ptr;
82  if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
83  FORMAT_MESSAGE_FROM_SYSTEM,
84  NULL,
85  last_error,
86  MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
87  (LPTSTR)&ptr,
88  0, NULL))
89  {
90  cout << "ERROR: " << " result = " << (char*) ptr << "\n";
91  LocalFree( ptr );
92  }
93  */
94 
95  switch (last_error) {
96  case 2: return "File not found";
97  case 3: return "Path not found";
98  case 4: return "Too many open files";
99  case 5: return "Access denied";
100  case 14: return "Out of memory";
101  case 18: return "No more files";
102  case 126: return "Module not found";
103  case 127: return "The specified procedure could not be found";
104  case 193: return "Not a valid Win32 application";
105  case 998: return "Invalid access to memory location";
106  }
107 
108  // Some unknown error code.
109  std::ostringstream errmsg;
110  errmsg << "Unknown error " << last_error;
111  return errmsg.str();
112 }
113 
114 void *
115 get_dso_symbol(void *handle, const string &name) {
116  // Windows puts a leading underscore in front of the symbol name.
117  return (void *)GetProcAddress((HMODULE)handle, name.c_str());
118 }
119 
120 /* end Win32-specific code */
121 
122 #else
123 /* begin Posix code */
124 
125 #if defined(IS_OSX)
126 #include <mach-o/dyld.h>
127 #endif
128 
129 #include <dlfcn.h>
130 
131 void *
132 load_dso(const DSearchPath &path, const Filename &filename) {
133  Filename abspath = resolve_dso(path, filename);
134  if (!abspath.is_regular_file()) {
135  // Make sure the error flag is cleared, to prevent a subsequent call to
136  // load_dso_error() from returning a previously stored error.
137  dlerror();
138  return nullptr;
139  }
140  string os_specific = abspath.to_os_specific();
141  return dlopen(os_specific.c_str(), RTLD_NOW | RTLD_GLOBAL);
142 }
143 
144 bool
145 unload_dso(void *dso_handle) {
146  return dlclose(dso_handle)==0;
147 }
148 
149 string
150 load_dso_error() {
151  const char *message = dlerror();
152  if (message != nullptr) {
153  return std::string(message);
154  }
155  return "No error.";
156 }
157 
158 void *
159 get_dso_symbol(void *handle, const string &name) {
160  return dlsym(handle, name.c_str());
161 }
162 
163 #endif
std::string get_dirname() const
Returns the directory part of the filename.
Definition: filename.I:358
get_dtool_name
Returns the name of the libdtool DLL that is used in this program, if it can be determined.
std::wstring to_os_specific_w() const
The wide-string variant on to_os_specific().
Definition: filename.cxx:1163
get_num_directories
Returns the number of directories on the search list.
Definition: dSearchPath.h:76
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
bool is_local() const
Returns true if the filename is local, e.g.
Definition: filename.I:549
bool is_regular_file() const
Returns true if the filename exists and is the name of a regular file (i.e.
Definition: filename.cxx:1297
get_directory
Returns the nth directory on the search list.
Definition: dSearchPath.h:76
This class stores a list of directories that can be searched, in order, to locate a particular file.
Definition: dSearchPath.h:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
Definition: filename.cxx:1123
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename find_file(const Filename &filename) const
Searches all the directories in the search list for the indicated file, in order.