Hi,
the context
I'm working on a project having some "modules". What I call a module here is a simple class, implementing a particular functionality and derivating from an abstract class GenericModule which force an interface.
New modules are supposed to be added in the future.
Several instances of a module can be loaded at the same time, or none, depending on the configuration file.
I though it would be great if a future developer could just "register" his module with the system in a simple line. More or less the same way they register tests in google test.
the context² (technical)
I'm building the project with visual studio 2005. The code is entirely in a library, except the main() which is in an exec project. I'd like to keep it that way.
my solution
I found inspiration in what they did with google test.
I created a templated Factory. which looks more or less like this (I've skipped uninteresting parts to keep this question somewhat readable ):
class CModuleFactory : boost::noncopyable
{
public:
virtual ~CModuleFactory() {};
virtual CModuleGenerique* operator()(
const boost::property_tree::ptree& rParametres ) const = 0;
};
template <class T>
class CModuleFactoryImpl : public CModuleFactory
{
public:
CModuleGenerique* operator()(
const boost::property_tree::ptree& rParametres ) const
{
return new T( rParametres );
}
};
and a method supposed to register the module and add it's factory to a list.
class CGenericModule
{
// ...
template <class T>
static int declareModule( const std::string& rstrModuleName )
{
// creation de la factory
CModuleFactoryImpl<T>* pFactory = new CModuleFactoryImpl<T>();
// adds the factory to a map of "id" => factory
CAcquisition::s_mapModuleFactory()[rstrModuleName ] = pFactory;
return 0;
}
};
now in a module all I need to do to declare a module is :
static int initModule =
acquisition::CGenericModule::declareModule<acquisition::modules::CMyMod>(
"mod_name"
);
( in the future it'll be wrapped in a macro allowing to do
DECLARE_MODULE( "mod_name", acquisition::modules::CMyMod );
)
the problem
Allright now the problem.
The thing is, it does work, but not exactly the way i'd want.
The method declareModule is not being called if I put the definition of the initModule in the .cpp of the module (where I'd like to have it) (or even in the .h). If I put the static init in a used .cpp file .. it works.
By used I mean : having code being called elsewhere.
The thing is visual studio seems to discard the entire obj when building the library. I guess that's because it's not being used anywhere.
I activated verbose linking and in pass n°2 it lists the .objs in the library and the .obj of the module isn't there.
almost resolved?
I found this and tried to add the /OPT:NOREF
option but it didn't work.
I didn't try to put a function in the .h of the module and call it from elsewhere, because the whole point is being able to declare it in one line in it's file.
Also I think the problem is similar to this one but the solution is for g++ not visual :'(
edit: I just read the note in the answer to this question. Well if I #include the .h of the module from an other .cpp, and put the init in the module's .h. It works and the initialization is actually done twice ... once in each compilation unit? well it seems it happens in the module's compilation unit ...
side notes
Please if you don't agree with what I'm trying to do, fell free to tell, but I'm still interested in a solution