Reputation:
This problem blocks me moving ahead. Please anyone kindly help me out.
My purpose is to implement a plugin factory which can create a plugin object by it's name(something like reflection, I guess?),
I define a namespace in header like:
// header file
namespace PluginFactory
{
using MFP = std::function<IPlugin*()>;
typedef std::map<std::string, MFP > mapType;
extern mapType g_ConstructMap;
//extern std::map<std::string, int> mMap;
extern IPlugin *CreateInstance(const std::string &className);
template<typename T>
IPlugin * createPlugin()
{
return new T;
}
template <typename T>
extern void InsertMap(const std::string &pluginName)
{
g_ConstructMap.insert(std::make_pair(pluginName, &createPlugin<T>));
//mMap.insert(std::make_pair(pluginName, 0));
}
}
// source file
namespace PluginFactory
{
mapType g_ConstructMap;
std::map<std::string, int> mMap;
IPlugin * CreateInstance(const std::string &className)
{
mapType::iterator it = g_ConstructMap.find(className);
if(it == g_ConstructMap.end())
{
qWarning("Construct %s failed. Not find a construct in map.", className.c_str());
return nullptr;
}
return it->second();
}
}
and the register
template<typename T>
class PluginFactoryRegister
{
public:
PluginFactoryRegister(const std::string &pluginName)
{
PluginFactory::InsertMap<T>(pluginName);
}
};
Register a specific plugin class into this system, using the macro:
#define REGISTER_DEF_TYPE(NAME) \
PluginFactoryRegister<NAME> NAME::regTbl(#NAME)
#define ADD_REGISTER_TABLE(NAME) \
static PluginFactoryRegister<NAME> regTbl
Finnaly, call insert function in PluginFactoryRegister
.
But, every time I run application, it complains Segment fault in exactly line:
namespace PluginFactory
{
...
g_ConstructMap.insert(std::make_pair(pluginName, &createPlugin<T>));
...
}
[Update 1] I'm using two macros for adding specific plugin classes(more than two such subclass) into my 'reflection system', like:
// example_plugin.h
class ExamplePlugin: public IPlugin
{
//...
// reflection
ADD_REGISTER_TABLE(ExamplePlugin);
}
// example_plugin.cpp
// ...
REGISTER_DEF_TYPE(ExamplePlugin);
// ...
And in some place, I will call CreateInstance
for create objects in a loop, like:
for(auto name : classnames)
{
IPlugin * newPlugin = PluginFactory::CreateInstance(name);
//...
}
Surely, I have tried many solutions, like define as class static map. That can barely help me.
Upvotes: 0
Views: 76
Reputation: 96043
This looks like a classical static initialization order fiasco.
The solution is to register classes without touching global variables, possibly by putting them into functions and making them static
.
Instead of mapType g_ConstructMap
, do something like
mapType &g_ConstructMap()
{
static mapType ret;
return ret;
}
and so on.
Upvotes: 3
Reputation: 567
I see a lot of pointers. Are you sure that you've properly initialised the map when you call insert on it?
I'd also suggest smart pointers.
Upvotes: -1