Field3D
PluginLoader.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
42 //----------------------------------------------------------------------------//
43 
44 #ifdef WIN32
45 #define WIN32_LEAN_AND_MEAN
46 #include <windows.h>
47 #else
48 #include <dlfcn.h>
49 #include <dirent.h>
50 #endif
51 
52 #include <sys/types.h>
53 #include <stdlib.h>
54 #include <string>
55 #include <vector>
56 #include <stdio.h>
57 #include <errno.h>
58 #include <string.h>
59 
60 #include <boost/tokenizer.hpp>
61 
62 #include "ClassFactory.h"
63 #include "PluginLoader.h"
64 
65 //----------------------------------------------------------------------------//
66 
67 using namespace std;
68 
69 //----------------------------------------------------------------------------//
70 // Local namespace
71 //----------------------------------------------------------------------------//
72 
73 namespace {
74 
75  void tokenize(const std::string &str, const std::string &delimiters,
76  std::vector<std::string> &retItems)
77  {
78  typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
79  boost::char_separator<char> sep(delimiters.c_str());
80  Tokenizer tok(str, sep);
81  for (Tokenizer::iterator i = tok.begin(); i != tok.end(); ++i) {
82  retItems.push_back(*i);
83  }
84  }
85 
86 }
87 
88 //----------------------------------------------------------------------------//
89 
91 
92 typedef int (*RegistrationFunc)(ClassFactory &);
93 
94 
95 //----------------------------------------------------------------------------//
96 // Static instances
97 //----------------------------------------------------------------------------//
98 
99 std::vector<std::string> PluginLoader::ms_pluginsLoaded;
100 
101 //----------------------------------------------------------------------------//
102 // PluginLoader implementations
103 //----------------------------------------------------------------------------//
104 
105 static int filter(std::string &name, const char *suffix)
106 {
107  std::string delimiters = ".";
108  std::vector <std::string> items;
109 
110  tokenize(name, delimiters, items);
111 
112  if (items.size() == 0) {
113  return 0;
114  }
115 
116  if (items[items.size() -1] == suffix) {
117  return 1;
118  }
119 
120  return 0;
121 }
122 
123 //----------------------------------------------------------------------------//
124 
125 bool getDirSos(std::vector<std::string> &sos, std::string &dir)
126 {
127 #ifdef WIN32
128  const char *ds = dir.c_str();
129  HANDLE dirh;
130  WIN32_FIND_DATAA fd;
131 
132  dirh = FindFirstFileA(ds, &fd);
133  while (dirh != INVALID_HANDLE_VALUE)
134  {
135  std::string name = fd.cFileName;
136  std::string name_lower;
137 
138  std::transform(name.begin(), name.end(), name_lower.begin(), ::tolower);
139 
140  if (filter(name_lower, "so")) {
141  name = dir + "/" + name;
142  sos.push_back(name);
143  }
144 
145  if (!FindNextFileA(dirh, &fd))
146  {
147  ::FindClose(dirh);
148  break;
149  }
150  }
151 #else
152  struct dirent *dirent;
153 
154  const char *ds = dir.c_str();
155  DIR *dirfd = opendir(ds);
156  if (!dirfd) {
157  std::string er =
158  "Field3D_plugin loader: could not open directory " + dir + "\n";
159  //perror(er.c_str());
160  return false;
161  }
162 
163  dirent = readdir(dirfd);
164  while (dirent != NULL) {
165 
166  std::string name = dirent->d_name;
167 
168  if (filter(name, "so")) {
169  name = dir + "/" + name;
170  sos.push_back(name);
171  }
172 
173  dirent = readdir(dirfd);
174  }
175 
176  closedir(dirfd);
177 #endif
178  return true;
179 }
180 
181 static RegistrationFunc findRegistrationFunc(const std::string &sofile)
182 {
183 #ifdef WIN32
184  HMODULE handle = ::LoadLibraryA(sofile.c_str());
185 #else
186  void *handle = dlopen(sofile.c_str(), RTLD_GLOBAL|RTLD_NOW);
187 #endif
188  // Attempt to load .so file
189  if (!handle) {
190  std::string errmsg;
191 #ifdef WIN32
192  char *errstr;
193 //----------------------------------------------------------------------------//
194  FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
195  NULL, GetLastError(),
196  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&errstr,
197  0, NULL);
198  if (errstr) {
199  errmsg = errstr;
200  ::LocalFree(errstr);
201  } else {
202  errmsg = "Unknown error";
203  }
204 #else
205  errmsg = dlerror();
206 #endif
207 
208  std::cout <<
209  "Field3D Plugin loader: failed to load plugin: " << errmsg << "\n";
210  return 0;
211  }
212 
213  // Determine plugin type by looking for one of:
214  // registerField3DPlugin()
215 
216  RegistrationFunc fptr;
217 
218 #ifdef WIN32
219  fptr = (RegistrationFunc)GetProcAddress(handle,"registerField3DPlugin");
220 #else
221  fptr = (RegistrationFunc)dlsym(handle,"registerField3DPlugin");
222 #endif
223  if (!fptr) {
224  char *debugEnvVar = getenv("FIELD3D_DEBUG");
225  if (debugEnvVar) {
226  // debug env var exist, so print warning
228  "Field3D plugin loader: failed to load "
229  "the symbol registerField3DPlugin");
230  }
231  }
232  return fptr;
233 }
234 
235 
236 //----------------------------------------------------------------------------//
237 
239 {
240 
241 }
242 
243 //----------------------------------------------------------------------------//
244 
246 {
247 
248 }
249 
250 //----------------------------------------------------------------------------//
251 
253 {
254  // Get environment variable
255  char *cptr = getenv("FIELD3D_DSO_PATH");
256  if (!cptr)
257  return;
258 
259  std::string path = cptr;
260 
261  // Split paths
262  std::vector<std::string> paths;
263  const std::string delimiters = ":";
264 
265  tokenize(path, delimiters, paths);
266 
267  // For each path
268  for (unsigned int i = 0; i < paths.size(); i++) {
269 
270  // List the contents of the directory
271  std::vector<std::string> sos;
272  if (!getDirSos(sos,paths[i])) {
273  continue;
274  }
275 
276  // Open each file
277  for (unsigned int j = 0; j < sos.size(); j++) {
278  std::string sofile = sos[j];
279 
280  //First check to see if a plugin of the same name has already been loaded
281  const std::string pathDelimiter = "/";
282  std::vector<std::string> pluginName;
283  tokenize(sofile, pathDelimiter, pluginName);
284 
285  bool pluginAlreadyLoaded = false;
286 
287  for (unsigned int i = 0; i < ms_pluginsLoaded.size(); i++) {
288  if (pluginName.size() > 0) {
289  if (ms_pluginsLoaded[i] == pluginName[pluginName.size() - 1]) {
290  //This plugin has been loaded so look for another one
291  //std::cout << ms_pluginsLoaded[i] << " is already loaded\n";
292  pluginAlreadyLoaded = true;
293  break;
294  }
295  }
296  }
297 
298  if (pluginAlreadyLoaded) {
299  continue;
300  }
301 
302  if (pluginName.size() > 0) {
303  std::string lastName = pluginName[pluginName.size() -1];
304  ms_pluginsLoaded.push_back(lastName);
305  }
306 
307  RegistrationFunc fptr;
308 
309  fptr = findRegistrationFunc(sofile);
310  if (fptr) {
311  // Call the registration function
312  int res = (*fptr)(ClassFactory::singleton());
313  if (!res) {
315  "failed to init Field3D plugin " + sofile);
316  } else {
317  Msg::print("Initialized Field3D Plugin " + sofile);
318  }
319  }
320  }
321  }
322 }
323 
324 //----------------------------------------------------------------------------//
325 
326 #if 0
327 
328 bool PluginLoader::getDso(char *cptr, const char *dso,
329  std::string &dsoPath)
330 {
331 
332  std::string path = cptr;
333 
334  // Split paths
335  std::vector<std::string> paths;
336  const std::string delimiters=":";
337 
338  Tokenize(path, paths, delimiters);
339 
340  // For each path
341  for (unsigned int i=0; i < paths.size(); i++) {
342  struct dirent *dirent;
343 
344  std::string dir = paths[i];
345  const char *ds = dir.c_str();
346  DIR *dirfd = opendir(ds);
347  if (!dirfd) {
348  continue;
349  }
350 
351  dirent = readdir(dirfd);
352  while (dirent != NULL) {
353 
354  std::string name = dirent->d_name;
355 
356  if (name == dso) {
357  dsoPath = dir + "/" + name;
358  closedir(dirfd);
359  return true;
360  }
361 
362  dirent = readdir(dirfd);
363  }
364  closedir(dirfd);
365  }
366 
367 
368  return false;
369 
370 }
371 
372 //----------------------------------------------------------------------------//
373 
374 bool PluginLoader::resolveGlobalsForPlugins(const char *dso) {
375 
376  // Get environment variable
377  char *cptr = getenv("HOUDINI_DSO_PATH");
378  if (!cptr)
379  return false;
380 
381  std::string sofile;
382  if (!getDso(cptr,dso,sofile)) {
383  std::string dsostring = dso;
384  Msg::print(dsostring + " is not in HOUDINI_DSO_PATH");
385  return false;
386  }
387 
388  void *handle = dlopen(sofile.c_str(), RTLD_GLOBAL|RTLD_NOW);
389 
390  if (!handle) {
391  std::cout << "Field3D Plugin loader: failed to load Houdini plugin: "
392  << sofile << " " << dlerror() << "\n";
393  return false;
394  }
395 
396 #if 0
397  Msg::print("---------------------------------------------------------");
398  Msg::print("Loaded " + sofile);
399  Msg::print("---------------------------------------------------------");
400 #endif
401 
402  return true;
403 
404 }
405 
406 #endif
407 
408 //----------------------------------------------------------------------------//
409 
411 
412 //----------------------------------------------------------------------------//
PluginLoader.h
Contains the PluginLoader class.
Msg::SevWarning
@ SevWarning
Definition: Log.h:68
PluginLoader::PluginLoader
PluginLoader()
Default constructor.
Definition: PluginLoader.cpp:238
ClassFactory
Definition: ClassFactory.h:72
PluginLoader::loadPlugins
static void loadPlugins()
Checks all paths in $FIELD3D_DSO_PATH and loads the plugins it finds.
Definition: PluginLoader.cpp:252
getDirSos
bool getDirSos(std::vector< std::string > &sos, std::string &dir)
Definition: PluginLoader.cpp:125
filter
static int filter(std::string &name, const char *suffix)
Definition: PluginLoader.cpp:105
ClassFactory::singleton
static ClassFactory & singleton()
}
Definition: ClassFactory.cpp:278
RegistrationFunc
FIELD3D_NAMESPACE_OPEN typedef int(* RegistrationFunc)(ClassFactory &)
Definition: PluginLoader.cpp:92
FIELD3D_NAMESPACE_SOURCE_CLOSE
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Definition: ns.h:60
FIELD3D_NAMESPACE_OPEN
Definition: FieldMapping.cpp:74
PluginLoader::ms_pluginsLoaded
static std::vector< std::string > ms_pluginsLoaded
List of plugins loaded.
Definition: PluginLoader.h:96
Msg::print
FIELD3D_API void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity.
Definition: Log.cpp:70
ClassFactory.h
Contains the ClassFactory class for registering Field3D classes.
PluginLoader::~PluginLoader
~PluginLoader()
Destructor.
Definition: PluginLoader.cpp:245
findRegistrationFunc
static RegistrationFunc findRegistrationFunc(const std::string &sofile)
Definition: PluginLoader.cpp:181