Я потратил несколько дней на поиск своей проблемы, но не смог найти никакого рабочего решения.
У меня есть класс с именем ServiceEventHub, который отвечает за диспетчеризацию событий в моем приложении.Код вдохновлен тем, что я нашел в сети для реализации агрегатора событий.Приложение представляет собой плагин движок, который динамически загружает различные DLL (плагины).Этот класс является службой, предоставляемой Механизмом, который находится внутри приложения (.exe).
Проблема заключается в том, что класс полагается на статические переменные для отслеживания различных «событий», генерируемых и регистрируемых.(события - это просто структуры, определенные в общем заголовочном файле).И из того, что я понимаю, из-за того, что символы не экспортируются по умолчанию в Windows, статические переменные не являются одинаковыми экземплярами в приложении и DLL.Как вы можете себе представить, «типы событий» не совпадают между движком и плагином, и он не ведет себя так, как ожидалось.Я впервые занимаюсь разработкой для Windows, и я немного растерялся.
Поскольку некоторые методы используют шаблон, я не могу переместить реализацию в файл cpp.Я пробовал метод dllexport / dllimport, но опять же он не работает, потому что класс использует шаблоны.Кроме того, в моем случае это приложение, которое экспортирует, и dll, которое импортирует, не уверенный, должно ли это работать так.
Я также посмотрел на #pragma data_seg
, но я не знаю, как его использовать .. для всего класса?Только 2 метода с использованием статики?
Вот полный код:
class ServiceEventHub
{
public:
template <class EventType>
using Slot = std::function<void(const EventType&)>;
ServiceEventHub()
{
}
template <typename EventType>
void subscribe(Slot<EventType> callable)
{
LOG_FUNC_ENTER();
std::lock_guard<std::recursive_mutex> lock(m_mutex);
size_t type = Event<EventType>::type();
if (type >= m_subscribers.size())
{
m_subscribers.resize(type + 1);
}
m_subscribers[type].push_back(CallbackWrapper<EventType>(callable));
}
template <typename EventType>
void emit(EventType&& event)
{
LOG_FUNC_ENTER(typeid(EventType).name());
// Critical section starts
std::lock_guard<std::recursive_mutex> lock(m_mutex);
size_t type = Event<EventType>::type();
if (type >= m_subscribers.size())
{
return;
}
Event<EventType> eventWrapper(std::forward<EventType>(event));
for (auto& receiver : m_subscribers[type])
{
m_ioService.post(boost::bind(receiver, eventWrapper));
}
// Critical section ends
}
private:
struct BaseEvent
{
virtual ~BaseEvent() {}
protected:
static size_t getNextType()
{
static size_t s_typeCount{ 0 };
return s_typeCount++;
}
};
template <typename EventType>
struct Event : BaseEvent
{
static size_t type()
{
static size_t s_type = BaseEvent::getNextType();
return s_type;
}
Event(EventType&& event)
: event_(std::forward<EventType>(event))
{
}
EventType event_;
};
template <typename EventType>
struct CallbackWrapper
{
CallbackWrapper(Slot<EventType> callable)
: m_callable(callable)
{
}
void operator()(const BaseEvent& event)
{
m_callable(static_cast<const Event<EventType>&>(event).event_);
}
Slot<EventType> m_callable;
};
void workerThread(boost::asio::io_service* ioService)
{
LOG_FUNC_ENTER();
ioService->run();
}
std::vector<std::vector<Slot<BaseEvent> > > m_subscribers = {};
std::recursive_mutex m_mutex;
boost::asio::io_service m_ioService{};
boost::asio::io_service::work m_ioWork{m_ioService};
std::thread m_thread{boost::bind(&ServiceEventHub::workerThread, this, &m_ioService)};
};
Любая помощь будет высоко ценится.