plugins_manager.cpp 9.31 KB
Newer Older
1
#include "plugins_manager.h"
2
3
#include "rational_function.h"
#include "vertical_segment.h"
4

5
/*
6
#include <QCoreApplication>
7
#include <QDir>
8
*/
9
10

#ifdef WIN32
11
    #include <windows.h>
12
13
14
#else
    #include <dlfcn.h>
#endif
15
#include <stdio.h>
16
17
18
19
20
21
22

//! \brief Open a dynamic library file (.so or .dll) and extract the associated
//! provide function. The template argument is used to cast the library to a
//! specific type.
template<typename T> T open_library(const std::string& filename, const char* function)
{
#ifdef WIN32
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    HINSTANCE handle = LoadLibrary((LPCTSTR)filename.c_str());
    if(handle != NULL)
    {
        T res = (T)GetProcAddress(handle, function);

        if(res == NULL)
        {
            std::cerr << "<<ERROR>> unable to load the symbol \"" << function << "\" from " << filename << std::endl;
            return NULL;
        }
#ifdef DEBUG_CORE
        std::cout << "<<DEBUG>> will provide a " << function << " for library \"" << filename << "\"" << std::endl;
#endif
        return res;
    }
    else
    {
        std::cerr << "<<ERROR>> unable to load the dynamic library file \"" << filename << "\"" << std::endl;
        std::cerr << "          cause: \"" << GetLastError() << "\"" << std::endl;
        return NULL;
    }
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#else
    void* handle = dlopen(filename.c_str(), RTLD_LAZY);
    if(handle != NULL)
    {
        void* res = dlsym(handle, function);

        if(dlerror() != NULL)
        {
            std::cerr << "<<ERROR>> unable to load the symbol \"" << function << "\" from " << filename << std::endl;
            return NULL;
        }
#ifdef DEBUG_CORE
        std::cout << "<<DEBUG>> will provide a " << function << " for library \"" << filename << "\"" << std::endl;
#endif
        return (T)res;
    }
    else
    {
        std::cerr << "<<ERROR>> unable to load the dynamic library file \"" << filename << "\"" << std::endl;
63
		  std::cerr << "          cause: \"" << dlerror() << "\"" << std::endl;
64
65
66
67
68
69
70
        return NULL;
    }
#endif
}


// Create the object, parse the argument and load all the plugins
71
72
plugins_manager::plugins_manager(const arguments& args) 
{
73
/*
74
75
76
77
78
79
80
81
82
	QDir pluginsDir;
	if(args.is_defined("plugins"))
	{
		pluginsDir = QDir(args["plugins"].c_str()) ;
	}
	else if(QCoreApplication::instance() != NULL)
	{
		pluginsDir = QDir(QCoreApplication::instance()->applicationDirPath());
	}
83
	*/
84

85
	/*
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
	foreach (QString fileName, pluginsDir.entryList(QDir::Files)) 
	{
		QPluginLoader loader ;
		loader.setLoadHints(QLibrary::ExportExternalSymbolsHint) ;
		loader.setFileName(pluginsDir.absoluteFilePath(fileName));
		
		// Convert filename for outputing		
		std::string filename(fileName.toStdString()) ;

		if(!loader.load())
		{
#ifdef DEBUG
			std::cout << "<<DEBUG>> " << loader.errorString().toStdString() << std::endl ;
#endif
			continue ;
		}

		QObject *plugin = loader.instance();
		if (plugin != NULL) 
		{
#ifdef DEBUG
			std::cout << "<<DEBUG>> loading plugin " << filename << std::endl ;
#endif
			if(dynamic_cast<function*>(plugin) != NULL)
			{
#ifdef DEBUG
				std::cout << "<<DEBUG>>  -> it is a function" << std::endl ;
#endif
				_functions.insert(std::pair<std::string, function*>(filename, dynamic_cast<function*>(plugin))) ;
			}
			
			if(dynamic_cast<data*>(plugin) != NULL)
			{
#ifdef DEBUG
				std::cout << "<<DEBUG>>  -> it is a data loader" << std::endl ;
#endif
				_datas.insert(std::pair<std::string, data*>(filename, dynamic_cast<data*>(plugin))) ;
			}
			if(dynamic_cast<fitter*>(plugin) != NULL)
			{
#ifdef DEBUG
				std::cout << "<<DEBUG>>  -> it is a fitter" << std::endl ;
#endif
				_fitters.insert(std::pair<std::string, fitter*>(filename, dynamic_cast<fitter*>(plugin))) ;
			}
		}
		else
		{
#ifdef DEBUG
			std::cout << "<<DEBUG>> " << loader.errorString().toStdString() << std::endl ;
#endif
		}
	}
139
	*/
140
141
142
143
144
}

// Get instances of the function, the data and the
// fitter
//
145
function* plugins_manager::get_function()
146
{
147
148
149
150
#ifdef USING_STATIC
    return new rational_function() ;
#else
    if(_functions.empty())
151
	{
152
		return new rational_function() ;
153
154
155
156
157
	}
	else
	{
		return _functions.begin()->second ;
	}
158
159
#endif

160
}
161
data* plugins_manager::get_data()
162
{
Laurent Belcour's avatar
Laurent Belcour committed
163
	//if(_datas.empty())
164
	{
165
166
167
#ifdef DEBUG
        std::cout << "<<DEBUG>>  using vertical segment data loader" << std::endl ;
#endif
168
		return new vertical_segment() ;
Laurent Belcour's avatar
Laurent Belcour committed
169
	}/*
170
171
	else
	{
172
#ifdef DEBUG
173
		std::cout << "<<DEBUG>>  using \"" << _datas.begin()->first << "\" data loader" << std::endl ;
174
#endif
175
		return _datas.begin()->second ;
Laurent Belcour's avatar
Laurent Belcour committed
176
	}*/
177
}
178
fitter* plugins_manager::get_fitter()
179
{
180
181
182
#ifdef USING_STATIC
    return NULL;
#else
183
184
185
186
187
188
	if(_fitters.empty())
	{
		return NULL ;
	}
	else
	{
189
#ifdef DEBUG
190
		std::cout << "<<DEBUG>>  using \"" <<  _fitters.begin()->first << "\"" << std::endl ;
191
#endif
192
193
		return _fitters.begin()->second ;
	}
194
#endif
195
196
}

197
198
199
//! Get an instance of the function selected based on the name <em>n</em>.
//! Return NULL if no one exist.
function* plugins_manager::get_function(const arguments& args)
200
{
201
    if(!args.is_defined("func"))
202
203
204
205
206
207
208
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no function plugin specified, returning a rational function" << std::endl;
#endif
        return new rational_function();
    }

209
    if(args.is_vec("func"))
210
    {
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
        std::vector<std::string> args_vec = args.get_vec("func");

        // Treating the case []
        if(args_vec.size() == 0)
        {
            return NULL;
        }

        //! \todo create a <em>compound</em> class to store multiple
        //! functions in it.

        //! For each args_vec element, create a function object and add
        //! it to the compound one.

        std::string n = args_vec[0];
        std::vector<std::string> cmd_vec;
        cmd_vec.push_back("--func");

        std::stringstream stream(n);
        while(stream.good())
        {
            std::string temp;
            stream >> temp;

            cmd_vec.push_back(temp);
        }
        int argc = cmd_vec.size();
        char* argv[argc];
        for(int i=0; i<argc; ++i)
        {
            argv[i] = &cmd_vec[i][0];
        }

        const arguments current_args(argc, argv);
        return get_function(current_args);

        //! return the compound class

249
250
251
    }
    else
    {
252
253
254
255
256
257
        std::string filename = args["func"];
        FunctionPrototype myFunction = open_library<FunctionPrototype>(filename, "provide_function");
        if(myFunction != NULL)
        {
#ifdef DEBUG
            std::cout << "<<DEBUG>> using function provider in file \"" << filename << "\"" << std::endl;
258
#endif
259
260
261
262
263
264
265
266
            return myFunction();
        }
        else
        {
            std::cerr << "<<ERROR>> no function provider found in file \"" << filename << "\"" << std::endl;
            return new rational_function() ;
        }
    }
267
}
268
data* plugins_manager::get_data(const std::string& n)
269
{
270
271
    if(n.empty())
    {
272
#ifdef DEBUG
273
        std::cout << "<<DEBUG>> no data plugin specified, returning a vertial_segment loader" << std::endl;
274
#endif
275
276
277
        return new vertical_segment();
    }

278
	 DataPrototype myData = open_library<DataPrototype>(n, "provide_data");
279
280
    if(myData != NULL)
    {
281
#ifdef DEBUG
282
283
284
285
286
287
288
289
290
        std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
        return myData();
    }
    else
    {
        std::cerr << "<<ERROR>> no data provider found in file \"" << n << "\"" << std::endl;
        return new vertical_segment() ;
    }
291
}
292
fitter* plugins_manager::get_fitter(const std::string& n)
293
{
Laurent Belcour's avatar
Laurent Belcour committed
294
295
296
297
298
299
300
301
    if(n.empty())
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no fitter plugin specified, returning null" << std::endl;
#endif
        return NULL;
    }

302
    FitterPrototype myFitter = open_library<FitterPrototype>(n, "provide_fitter");
Laurent Belcour's avatar
Laurent Belcour committed
303
304
305
306
307
308
309
310
311
    if(myFitter != NULL)
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
        return myFitter();
    }
    else
    {
312
313
        std::cerr << "<<ERROR>> no fitter provider found in file \"" << n << "\"" << std::endl;
        return NULL ;
Laurent Belcour's avatar
Laurent Belcour committed
314
    }
315
}
316

Laurent Belcour's avatar
Laurent Belcour committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
void plugins_manager::check_compatibility(data*& d, function*& f,
                                          const arguments& args)
{
	if(d->parametrization() == params::UNKNOWN_INPUT)
	{
		std::cout << "<<WARNING>> unknown parametrization for data" << std::endl;
	}

	if(f->parametrization() == params::UNKNOWN_INPUT)
	{
		std::cout << "<<DEBUG>> function will take the parametrization of the data" << std::endl;
		f->setParametrization(d->parametrization());
	}
	else if(d->parametrization() != f->parametrization())
	{
		std::cout << "<<INFO>> has to change the parametrization of the input data" << std::endl;
		data_params* dd = new data_params(d, f->parametrization());
		d = dd ;
	}
	else
	{
		std::cout << "<<DEBUG>> no change was made to the parametrization" << std::endl;
	}

	if(f->dimY() != d->dimY())
	{
		std::cout << "<<WARNING>> the data and the function have different Y dimensions" << std::endl;
	}

	/*
	// Check is the data has to be clusterized
	if(args.is_defined("cluster-dim"))
	{
	clustering* cluster = new clustering(d, args);
	d = cluster;
	}
	*/
}
355
356
357
358
		
// \todo implement the Darwin (MACOS) version.
#ifdef WIN32
#include <windows.h>
359
size_t plugins_manager::get_system_memory()
360
361
362
363
364
365
366
367
{
	MEMORYSTATUSEX status;
	status.dwLength = sizeof(status);
	GlobalMemoryStatusEx(&status);
	return status.ullTotalPhys;
}
#else
#include <unistd.h>
368
size_t plugins_manager::get_system_memory()
369
370
371
372
373
374
{
	long pages = sysconf(_SC_PHYS_PAGES);
	long page_size = sysconf(_SC_PAGE_SIZE);
	return pages * page_size;
}
#endif