plugins_manager.cpp 7.73 KB
Newer Older
1
#include "plugins_manager.h"
2 3
#include "rational_function.h"
#include "vertical_segment.h"
4 5 6 7

#include <QCoreApplication>
#include <QPluginLoader>
#include <QtPlugin>
8
#include <QLibrary>
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
#include <QDir>

// Create the object, parse the argument and load
// all the plugins
//
plugins_manager::plugins_manager(const arguments& args) 
{

	QDir pluginsDir;
	if(args.is_defined("plugins"))
	{
		pluginsDir = QDir(args["plugins"].c_str()) ;
	}
	else if(QCoreApplication::instance() != NULL)
	{
		pluginsDir = QDir(QCoreApplication::instance()->applicationDirPath());
	}

	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
		}
	}
}

82 83 84 85 86 87
#ifdef USING_STATIC
typedef function* (*FunctionPrototype)();
typedef fitter*   (*FitterPrototype)();
typedef data*     (*DataPrototype)();
#endif

88 89 90
// Get instances of the function, the data and the
// fitter
//
91
function* plugins_manager::get_function()
92
{
93 94 95 96
#ifdef USING_STATIC
    return new rational_function() ;
#else
    if(_functions.empty())
97
	{
98
		return new rational_function() ;
99 100 101 102 103
	}
	else
	{
		return _functions.begin()->second ;
	}
104 105
#endif

106
}
107
data* plugins_manager::get_data()
108
{
Laurent Belcour's avatar
Laurent Belcour committed
109
	//if(_datas.empty())
110
	{
111 112 113
#ifdef DEBUG
        std::cout << "<<DEBUG>>  using vertical segment data loader" << std::endl ;
#endif
114
		return new vertical_segment() ;
Laurent Belcour's avatar
Laurent Belcour committed
115
	}/*
116 117
	else
	{
118
#ifdef DEBUG
119
		std::cout << "<<DEBUG>>  using \"" << _datas.begin()->first << "\" data loader" << std::endl ;
120
#endif
121
		return _datas.begin()->second ;
Laurent Belcour's avatar
Laurent Belcour committed
122
	}*/
123
}
124
fitter* plugins_manager::get_fitter()
125
{
126 127 128
#ifdef USING_STATIC
    return NULL;
#else
129 130 131 132 133 134
	if(_fitters.empty())
	{
		return NULL ;
	}
	else
	{
135
#ifdef DEBUG
136
		std::cout << "<<DEBUG>>  using \"" <<  _fitters.begin()->first << "\"" << std::endl ;
137
#endif
138 139
		return _fitters.begin()->second ;
	}
140
#endif
141 142
}

Laurent Belcour's avatar
Laurent Belcour committed
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
#ifdef WIN32
#else
    #include <stdio.h>
    #include <dlfcn.h>
#endif

void* open_library(const std::string& filename, const char* function)
{
#ifdef WIN32
    return NULL;
#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 res;
    }
    else
    {
        return NULL;
    }
#endif
}
172

173 174 175 176
// Get instances of the function, the data and the
// fitter, select one based on the name. Return null
// if no one exist.
//
177
function* plugins_manager::get_function(const std::string& n)
178
{
179 180 181 182 183 184 185 186
    if(n.empty())
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no function plugin specified, returning a rational function" << std::endl;
#endif
        return new rational_function();
    }

187
#ifdef USING_STATIC
Laurent Belcour's avatar
Laurent Belcour committed
188 189 190 191 192 193 194 195 196 197 198
	 std::string file;
	 if(n[0] == '.')
	 {
		 file = n.substr(1, n.size()-1);
	 }
	 else
	 {
		 file = n;
	 }

    QString path = QDir::currentPath() + QString(file.c_str()) ;
199 200 201 202 203 204 205
    QLibrary function_lib(path);
    if(!function_lib.isLoaded())
    {
        std::cerr << "<<ERROR>> unable to load file \"" << path.toStdString() << "\"" << std::endl;
        return NULL;
    }

206
    FunctionPrototype myFunction = (FunctionPrototype) function_lib.resolve("provide_function");
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221

    if(myFunction != NULL)
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
        return myFunction();
    }
    else
    {
        std::cerr << "<<ERROR>> no function provider found in file \"" << n << "\"" << std::endl;
        return new rational_function() ;
    }
#else

222
	if(_functions.count(n) == 0)
223
	{
224
		return new rational_function() ;
225 226 227
	}
	else
	{
Laurent Belcour's avatar
Laurent Belcour committed
228
		return _functions.find(n)->second ;
229
	}
230
#endif
231
}
232
data* plugins_manager::get_data(const std::string& n)
233
{
234 235
    if(n.empty())
    {
236
#ifdef DEBUG
237
        std::cout << "<<DEBUG>> no data plugin specified, returning a vertial_segment loader" << std::endl;
238
#endif
239 240 241 242
        return new vertical_segment();
    }

#ifdef USING_STATIC
Laurent Belcour's avatar
Laurent Belcour committed
243 244 245 246 247 248 249 250 251 252 253
	 std::string file;
	 if(n[0] == '.')
	 {
		 file = n.substr(1, n.size()-1);
	 }
	 else
	 {
		 file = n;
	 }

    QString path = QDir::currentPath() + QString(file.c_str()) ;
254 255 256 257 258 259 260
    QLibrary data_lib(path);
    if(!data_lib.isLoaded())
    {
        std::cerr << "<<ERROR>> unable to load file \"" << path.toStdString() << "\"" << std::endl;
        return NULL;
    }

261
    DataPrototype myData = (DataPrototype) data_lib.resolve("provide_data");
262 263 264

    if(myData != NULL)
    {
265
#ifdef DEBUG
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
        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() ;
    }
#else

    if(_functions.count(n) == 0)
    {
        return new vertical_segment() ;
    }
    else
    {
        return _datas.find(n)->second ;
    }
285
#endif
286
}
287
fitter* plugins_manager::get_fitter(const std::string& n)
288
{
Laurent Belcour's avatar
Laurent Belcour committed
289 290 291 292 293 294 295 296
    if(n.empty())
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no fitter plugin specified, returning null" << std::endl;
#endif
        return NULL;
    }

297
#ifdef USING_STATIC
Laurent Belcour's avatar
Laurent Belcour committed
298 299 300 301 302 303 304 305 306 307 308
	 std::string file;
	 if(n[0] == '.')
	 {
		 file = n.substr(1, n.size()-1);
	 }
	 else
	 {
		 file = n;
	 }

    QString path = QDir::currentPath() + QString(file.c_str()) ;
309 310 311 312 313 314 315
    QLibrary fitting_lib(path);
    if(!fitting_lib.isLoaded())
    {
        std::cerr << "<<ERROR>> unable to load file \"" << path.toStdString() << "\"" << std::endl;
        return NULL;
    }

316
	FitterPrototype myFitter = (FitterPrototype) fitting_lib.resolve("provide_fitter");
Laurent Belcour's avatar
Laurent Belcour committed
317 318 319 320 321 322 323 324 325 326

    if(myFitter != NULL)
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
        return myFitter();
    }
    else
    {
327 328
        std::cerr << "<<ERROR>> no fitter provider found in file \"" << n << "\"" << std::endl;
        return NULL ;
Laurent Belcour's avatar
Laurent Belcour committed
329 330
    }
#else
331
	if(_fitters.count(n) == 0)
332 333 334 335 336
	{
		return NULL ;
	}
	else
	{
337
#ifdef DEBUG
338
		std::cout << "<<DEBUG>>  using \"" <<  n << "\"" << std::endl ;
339
#endif
Laurent Belcour's avatar
Laurent Belcour committed
340
		return _fitters.find(n)->second ;
341
	}
Laurent Belcour's avatar
Laurent Belcour committed
342
#endif
343
}
344 345 346 347
		
// \todo implement the Darwin (MACOS) version.
#ifdef WIN32
#include <windows.h>
348
size_t plugins_manager::get_system_memory()
349 350 351 352 353 354 355 356
{
	MEMORYSTATUSEX status;
	status.dwLength = sizeof(status);
	GlobalMemoryStatusEx(&status);
	return status.ullTotalPhys;
}
#else
#include <unistd.h>
357
size_t plugins_manager::get_system_memory()
358 359 360 361 362 363
{
	long pages = sysconf(_SC_PHYS_PAGES);
	long page_size = sysconf(_SC_PAGE_SIZE);
	return pages * page_size;
}
#endif