libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNModule.h
Go to the documentation of this file.
1 /* Copyright 2010-2014 CoReNum, INSA-Lyon
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libcrn is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: Module.h
19  * \author Yann LEYDIER
20  */
21 
22 #ifndef CRNModule_HEADER
23 #define CRNModule_HEADER
24 
25 #include <CRNString.h>
26 #include <CRNIO/CRNIO.h>
27 
28 #ifdef _MSC_VER
29 # include <windows.h>
30 // this is insane!!!
31 # undef GetClassName
32 # undef DELETE
33 # undef ABSOLUTE
34 # undef max
35 # undef min
36 # undef RGB
37 # include <errno.h>
38  inline HMODULE dlopen(const char *P, int G)
39  {
40  return LoadLibrary(P);
41  }
42 # define dlsym(D,F) (void*)GetProcAddress((HMODULE)D,F)
43 # define dlclose(D) FreeLibrary((HMODULE)D)
44  inline const char* dlerror()
45  {
46  static char szMsgBuf[256];
47  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
48  nullptr,
49  GetLastError(),
50  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
51  szMsgBuf,
52  sizeof szMsgBuf,
53  nullptr);
54  return szMsgBuf;
55  }
56 # define RTLD_LAZY 1
57 # define RTLD_NOW 2
58 # define RTLD_GLOBAL 4
59 #else
60 # include <dlfcn.h>
61 #endif /* _MSC_VER */
62 
66 namespace crn
67 {
78  template<class Category> class ModuleManager
79  {
80  public:
89  int LoadDirectory(const Path &dirname, const String &ext = U"")
90  {
91  try
92  {
93  crn::IO::Directory dir(dirname);
94  int cnt = 0;
95  for (const crn::Path filename : dir.GetFiles())
96  { // for each file in the directory
97  if (ext.IsNotEmpty())
98  { // check extension
99  if (filename.SubString(filename.Size() - ext.Size()) != ext)
100  {
101  continue;
102  }
103  }
104  void *handle = dlopen(filename.CStr(), RTLD_NOW | RTLD_GLOBAL);
105  if (handle)
106  { // if the file is a loadable library
107  handles.push_back(handle);
108  Category* (*handleget)(void);
109  handleget = (Category* (*)(void))dlsym(handle, Category::GetModuleEntryPoint());
110  if (handleget)
111  { // if there is a crn_module_get function
112  if (RegisterModule(std::shared_ptr<Category>(handleget())))
113  cnt += 1;
114  }
115  else
116  { // no crn_module_get_XXX function
117  CRNDebug(String(U"int module::LoadDirectory(const String &dirname): Cannot find entry point in file ") + filename + String(U" (") + dlerror() + String(U")"));
118  }
119  }
120  else
121  { // not a loadable library
122  CRNError(String(U"int module::LoadDirectory(const String &dirname): Cannot open file ") + filename + String(U" (") + dlerror() + String(U")"));
123  }
124  }
125  return cnt;
126  }
127  catch (...)
128  { // directory not found
129  CRNError(crn::String(U"int module::LoadDirectory(const String &dirname): Cannot open directory ") + dirname);
130  return 0;
131  }
132  }
133 
135  std::vector<std::shared_ptr<Category>> GetModules() const
136  {
137  return modules;
138  }
139 
141  bool RegisterModule(std::shared_ptr<Category> mod)
142  {
143  if (!mod)
144  {
145  CRNError(String(U"bool ModuleManager::RegisterModule(Category *mod): The module is of wrong category."));
146  return false;
147  }
148  else
149  {
150  modules.push_back(mod);
151  return true;
152  }
153  }
154 
159  {
160  modules.clear(); // free all pointers before we close the libs!
161  for (void *h : handles)
162  {
163  dlclose(h);
164  }
165  }
166  private:
167  std::vector<void*> handles;
168  std::vector<std::shared_ptr<Category> > modules;
169  };
170 
171 }
172 
177 #define CRN_MODULE_ENTRY_POINT(category) crn_module_get_##category
178 
182 #define CRN_MODULE_ENTRY_POINT_AS_STRING(category) "crn_module_get_"#category
183 
192 #define CRN_DECLARE_MODULE(categoryname) public: static const char* GetModuleEntryPoint() { return CRN_MODULE_ENTRY_POINT_AS_STRING(categoryname); }
193 
212 #define CRN_BEGIN_MODULE(classname, categoryname) class classname: public categoryname {
213 
232 #define CRN_END_MODULE(classname, categoryname) }; extern "C" categoryname* CRN_MODULE_ENTRY_POINT(categoryname)() { return new classname; }
233 
234 #endif
235 
int LoadDirectory(const Path &dirname, const String &ext=U"")
Loads modules contained in a directory.
Definition: CRNModule.h:89
bool RegisterModule(std::shared_ptr< Category > mod)
Registers a new module. DO NOT USE THIS METHOD DIRECTLY. Call CRN_BEGIN/END_MODULE.
Definition: CRNModule.h:141
~ModuleManager()
Destructor frees handles.
Definition: CRNModule.h:158
#define CRNDebug(x)
Definition: CRNIO.h:141
A handler to the content of a directory.
Definition: CRNIO.h:116
A UTF32 character string class.
Definition: CRNString.h:61
ModuleManager()
Default constructor.
Definition: CRNModule.h:156
A convenience class for file paths.
Definition: CRNPath.h:39
#define CRNError(x)
Definition: CRNIO.h:147
A dynamic module manager.
Definition: CRNModule.h:78
const std::vector< Path > & GetFiles() const
Returns the list of files.
Definition: CRNIO.h:122
std::vector< std::shared_ptr< Category > > GetModules() const
Retrieves the modules that implement a given interface.
Definition: CRNModule.h:135