У меня есть фабрика, которая регистрирует классы в коллекцию.Фабрика находится в dll, а регистрация классов может быть в другой dll.Регистрация работает нормально, когда класс вызывает REGISTER_CLASS из с в той же самой dll, но не когда внешний класс вызывает его.
Оспаривающая строка: #define REGISTER_CLASS (T) static ClassMaker maker (#T);
I have tried to wrap the #define REGISTER_CLASS with extern "C"{ }
I have tried to declare it to export with the OPTUMDATA_API
#ifdef OPTUMDATA_EXPORTS
#define OPTUMDATA_API __declspec(dllexport)
#else
#define OPTUMDATA_API __declspec(dllimport)
#endif
OFactory, ClassMaker находятся в своей собственной dll.
Внешний класс находится в своей собственной dll.
Пример OFactory.h
#include "dlldef.h"
#include "OCollectable.h"
#include "IClassMaker.h"
#include <string>
#include <map>
class OPTUMDATA_API BaseFactory {
public:
static BaseFactory& Instance(); // Factory is a singleton
// Adds new class maker with a given key ( class name )
void RegisterMaker (const std::string&key, IClassMaker * maker);
// Creates new IClass from unknown class name
OCollectable* Create (std::string node) const;
OCollectable* Create(std::string node, OCollectable& oCol) const;
private:
BaseFactory() {}
BaseFactory(const BaseFactory& other);
BaseFactory& operator=(const BaseFactory& other);
std::map<std::string, IClassMaker*> _makers;
};
Пример OFactory.cpp
#include "OFactory.h"
#include <string>
#include <vector>
#include "IClassMaker.h"
#include "OCollectable.h"
#include <Windows.h>
BaseFactory& BaseFactory::Instance()
{
static BaseFactory factory;
return factory;
}
void BaseFactory::RegisterMaker(const std::string& key, IClassMaker* maker)
{
// Validate uniquness and add to the map
if (_makers.find(key) != _makers.end())
{
throw new std::exception("Multiple makers for given key!");
}
_makers[key] = maker;
}
OCollectable* BaseFactory::Create(std::string node) const
{
std::vector<std::string> strs;
boost::split(strs,node,boost::is_any_of(" "));
// Look up the maker by nodes name
std::string key(strs[0]);
auto i = _makers.find(key);
if (i == _makers.end())
{
throw new std::exception("Oject has not been registered!");
}
IClassMaker* maker = i->second;
// Invoke create polymorphiclly
return maker->Create(node);
}
OCollectable* BaseFactory::Create(std::string node, OCollectable& oCol)
const
{
std::vector<std::string> strs;
boost::split(strs,node,boost::is_any_of(" "));
// Look up the maker by nodes name
std::string key(strs[0]);
auto i = _makers.find(key);
if (i == _makers.end())
{
throw new std::exception("Oject has not been registered!");
}
IClassMaker* maker = i->second;
// Invoke create polymorphiclly
return maker->Create(node,oCol);
}
Например: ClassMaker.h
#include "IClassMaker.h"
#include "OCollectable.h"
#include "OFactory.h"
#define REGISTER_CLASS(T) static ClassMaker<T> maker(#T);
template<typename T>
class OPTUMDATA_API ClassMaker : public IClassMaker
{
public:
/// When created, the class maker will automaticly register itself with
the factory
/// Note - you are discouraged from using ClassMaker outside
REGISTER_CLASS macro
/// For example, creating ClassMaker on the stack will end up badly
ClassMaker(const std::string& key)
{
BaseFactory::Instance().RegisterMaker(key, this);
}
virtual OCollectable* Create(std::string node) const
{
std::vector<std::string> strs;
boost::split(strs,node,boost::is_any_of(" "));
//// Create new instance of T using constructor from string
//// Assumes T has a constructor that accepts std::string
//std::string str = fields[1];
return new T(strs[1].c_str());
}
virtual OCollectable* Create(std::string node, OCollectable& oCol) const
{
std::vector<std::string> strs;
boost::split(strs,node,boost::is_any_of(" "));
//// Create new instance of T using constructor from string
//// Assumes T has a constructor that accepts std::string
//std::string str = fields[1];
return new T(strs[1].c_str(), oCol);
}
};
Внешний класс Пример .cpp файл
#include "term_store.h"
#include "ClassMaker.h"
#include "OFactory.h"
REGISTER_CLASS(TermStringClass);
using namespace std;
// Term String Class member functions
// Constructors
TermStringClass::TermStringClass(const TermStringClass &ts): term(ts.term)
{}
TermStringClass::TermStringClass(const OString &t): term(t){}
TermStringClass::TermStringClass(const OString &t, OCollectable& s):
term(t){}
TermStringClass::TermStringClass(const char *t): term(t) {}
TermStringClass::TermStringClass() {
}
TermStringClass::~TermStringClass() {
}
Внешний класс Пример .hфайл
#include <ClassMaker.h>
#include <OFactory.h>
//using namespace std;
class TermStringClass: public OCollectable {
public:
// Constructors
TermStringClass(const TermStringClass &ts);
TermStringClass(const OString &t);
TermStringClass(const OString &t, OCollectable& s);
TermStringClass(const char *t);
TermStringClass();
virtual ~TermStringClass();
};
Получение ошибок компоновщика во внешнем классе .obj файл
Ошибка 64 ошибка LNK2019: неразрешенный внешний символ "__declspec (dllimport) public: __thiscall ClassMaker :: ClassMaker (класс std ::basic_string, класс std :: allocator> const &) "(__imp _ ?? 0? $ ClassMaker @ VTermStringClass @@@@ QAE @ ABV? $ basic_string @ DU? $ char_traits @ D @ std @@ V? $ allocator @ D @2 @@ std @@@ Z) упоминается в функции "void __cdecl` динамический инициализатор для 'maker' '(void) "(?? __ Emaker @@ YAXXZ)