242 lines
5.5 KiB
C++
242 lines
5.5 KiB
C++
/**
|
|
* moduleLoader.h
|
|
* Author: Daniel Karrels (dan@karrels.com)
|
|
* Copyright (C) 2002 Daniel Karrels <dan@karrels.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
* USA.
|
|
*
|
|
* $Id: moduleLoader.h,v 1.21 2004/05/18 16:50:57 dan_karrels Exp $
|
|
*/
|
|
|
|
#ifndef __MODULELOADER_H
|
|
#define __MODULELOADER_H "$Id: moduleLoader.h,v 1.21 2004/05/18 16:50:57 dan_karrels Exp $"
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
#include <cstdlib> // exit()
|
|
#include "ltdl.h"
|
|
|
|
#include "ELog.h"
|
|
|
|
namespace gnuworld
|
|
{
|
|
|
|
/**
|
|
* This is a templated module loader class. The templated type is the
|
|
* type of object to retrieve from the module. This class is used with
|
|
* libtool for maximum portability.
|
|
*/
|
|
template< typename modType, typename argType = std::string >
|
|
class moduleLoader
|
|
{
|
|
|
|
protected:
|
|
|
|
/**
|
|
* This is the type of the bootstrap function.
|
|
*/
|
|
typedef modType (*GNUWModuleFunc)(argType arg) ;
|
|
|
|
/**
|
|
* Pointer to the loaded module.
|
|
*/
|
|
lt_dlhandle moduleHandle ;
|
|
|
|
/**
|
|
* Pointer to the initialisation function.
|
|
*/
|
|
GNUWModuleFunc modFunc ;
|
|
|
|
/**
|
|
* Pointer to the object being retrieved from the
|
|
* module.
|
|
*/
|
|
modType modPtr ;
|
|
|
|
/**
|
|
* The name of the module which this instance represents.
|
|
*/
|
|
std::string moduleName ;
|
|
|
|
/**
|
|
* This variable is true if there was an error in loading
|
|
* or resolving a symbol, false otherwise.
|
|
*/
|
|
bool hasError ;
|
|
|
|
/**
|
|
* Provide a protected mutator for this class to use to modify
|
|
* the error value.
|
|
*/
|
|
inline void setError( bool newVal = true )
|
|
{ hasError = newVal ; }
|
|
|
|
public:
|
|
/**
|
|
* Constructor, takes a module filename as the only
|
|
* parameter.
|
|
*/
|
|
moduleLoader( const std::string& _moduleName )
|
|
: moduleName( _moduleName ),
|
|
hasError( false )
|
|
{
|
|
// Initialize the function pointer to 0
|
|
modFunc = 0 ;
|
|
|
|
// Must call lt_dlinit() to initialize libltdl.
|
|
// This method may be called more than once
|
|
if( lt_dlinit() != 0 )
|
|
{
|
|
elog << "moduleLoader> Failed to initialize "
|
|
<< "module loading system: "
|
|
<< lt_dlerror()
|
|
<< std::endl ;
|
|
setError() ;
|
|
return ;
|
|
}
|
|
|
|
std::string fileName( moduleName ) ;
|
|
if( fileName[ 0 ] != '/' )
|
|
{
|
|
// No absolute path specified
|
|
// Attempt to find the module in the currect directory
|
|
fileName = std::string( "./" ) + fileName ;
|
|
}
|
|
|
|
// Libtool libraries end with .la, and at this point, this class
|
|
// only supports libtool libraries
|
|
if( std::string::npos == fileName.find( ".la" ) )
|
|
{
|
|
// TODO: This should be more thorough
|
|
fileName += ".la" ;
|
|
}
|
|
|
|
// elog << "moduleLoader> Attempting to load module "
|
|
// << fileName
|
|
// << std::endl;
|
|
|
|
// lt_dlopenext() will do all that lt_dlopen() does,
|
|
// but also check for .la, .so, .sl, etc extensions
|
|
moduleHandle = lt_dlopen( fileName.c_str() ) ;
|
|
|
|
if( 0 == moduleHandle )
|
|
{
|
|
elog << "moduleLoader> Error opening module ("
|
|
<< moduleName
|
|
<< "): "
|
|
<< lt_dlerror()
|
|
<< std::endl;
|
|
setError() ;
|
|
return ;
|
|
}
|
|
|
|
// elog << "moduleLoader> Module "
|
|
// << moduleName
|
|
// << " successfully loaded"
|
|
// << std::endl;
|
|
}
|
|
|
|
/**
|
|
* The destructor closes the module, but does not perform
|
|
* any other deallocation.
|
|
*/
|
|
virtual ~moduleLoader()
|
|
{
|
|
if( lt_dlclose( moduleHandle ) != 0 )
|
|
{
|
|
elog << "~moduleLoader> Error closing module: "
|
|
<< lt_dlerror()
|
|
<< std::endl ;
|
|
}
|
|
moduleHandle = 0 ;
|
|
}
|
|
|
|
/**
|
|
* Extracts an instance of modType
|
|
* derived object from this module, and returns it.
|
|
* This method will execute only once for each instance.
|
|
* Each additional call after the initial call to laodObject()
|
|
* will return the object previously created.
|
|
* The symbolSuffix is used to distinguish between similarly
|
|
* named symbols to be loaded from the same module.
|
|
*/
|
|
modType loadObject( argType arg,
|
|
const std::string& symbolSuffix = std::string() )
|
|
{
|
|
if( getError() )
|
|
{
|
|
// Error already present
|
|
return 0 ;
|
|
}
|
|
|
|
const std::string symbolName =
|
|
std::string( "_gnuwinit" ) + symbolSuffix ;
|
|
modFunc = (GNUWModuleFunc) lt_dlsym( moduleHandle,
|
|
symbolName.c_str() ) ;
|
|
if( 0 == modFunc )
|
|
{
|
|
elog << "moduleLoader::loadObject> Error: "
|
|
<< lt_dlerror()
|
|
<< std::endl ;
|
|
setError() ;
|
|
return 0 ;
|
|
}
|
|
|
|
modPtr = modFunc( arg );
|
|
|
|
// Types usable by this class must support comparison against 0
|
|
if( 0 == modPtr )
|
|
{
|
|
elog << "moduleLoader> Unable to instantiate modType."
|
|
<< std::endl;
|
|
setError() ;
|
|
}
|
|
|
|
return modPtr ;
|
|
}
|
|
|
|
/**
|
|
* Return a string containing the module's name, as passed
|
|
* to the constructor
|
|
*/
|
|
inline const std::string& getModuleName() const
|
|
{ return moduleName ; }
|
|
|
|
/**
|
|
* Return the last error seen by the module system.
|
|
*/
|
|
inline const std::string& getLastError() const
|
|
{ return ::lt_dlerror() ; }
|
|
|
|
/**
|
|
* Return by value the object being loaded from the module.
|
|
*/
|
|
inline modType getObject() const
|
|
{ return modPtr ; }
|
|
|
|
/**
|
|
* Return true if an error occured, false otherwise.
|
|
*/
|
|
inline bool getError() const
|
|
{ return hasError ; }
|
|
|
|
} ;
|
|
|
|
} /* gnuworld */
|
|
|
|
#endif /* __MODULELOADER_H */
|