C ++ Export #define и ссылка в другую DLL - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть фабрика, которая регистрирует классы в коллекцию.Фабрика находится в 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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...