Ошибки компоновщика Windows DLL с классом шаблона

template <typename sendertype__,="" typename...="" args__="">
class CORE_API Event
{
public:
 typedef typename std::function<void(const sendertype__*,="" args__="" ...)=""> EventHandler; 

 Event& operator+=(const EventHandler& toSubscribe)
 {
 Subscribe(toSubscribe);
 return *this;
 }

 void operator()(const SenderType__* sender, Args__ ... args) const
 {
 Invoke(sender, args...);
 }

 void Subscribe(const EventHandler& toSubscribe)
 {
 std::lock_guard<std::mutex> locker(m_callbackMutex);
 m_callbacks.push_back(toSubscribe);
 }

 void Clear()
 {
 std::lock_guard<std::mutex> locker(m_callbackMutex);
 m_callbacks.clear();
 }

 void Invoke(const SenderType__* sender, Args__ ... args) const
 {
 std::lock_guard<std::mutex> locker(m_callbackMutex);
 for (auto iter = m_callbacks.begin(); iter != m_callbacks.end(); ++iter)
 {
 (*iter)(sender, args...);
 }
 }

private:
 std::vector<eventhandler> m_callbacks;
 mutable std::mutex m_callbackMutex;
};

template class CORE_API Event<std::string, std::string="">;
</std::string,></eventhandler></std::mutex></std::mutex></std::mutex></void(const></typename>

У потребителя DLL....

TEST(EventTest, TestEventFiresAndPassesArgs)
{
 Event<std::string, std::string=""> event;
 event += &TestFunction;
 event += &TestFunction2;
 std::string sender = "TestEventFiresAndPassesArgs";
 std::string arg = "boo!";
 event.Invoke(&sender, arg);
 ASSERT_EQ(sender, testEventFiresAndPassesArgsSenderName);
 ASSERT_EQ(arg, testEventFiresAndPassesArgsTestArg);
 ASSERT_EQ(sender + "Function2", testEventFiresAndPassesArgsSenderName2);
 ASSERT_EQ(arg + "Function2", testEventFiresAndPassesArgsTestArg2);
}
</std::string,>

Тогда выход компоновщика:

EventTest.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: class CompanyName::Utils::Event<class std::basic_string<char,struct="" std::char_traits<char="">,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> > > & __cdecl CompanyName::Utils::Event<class std::basic_string<char,struct="" std::char_traits<char="">,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> > >::operator+=(class std::function<void __cdecl(class="" std::basic_string<char,struct="" std::char_traits<char="">,class std::allocator<char> > const *,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> >)> const &)" (__imp_??Y?$Event@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@Utils@CompanyName@@QEAAAEAV012@****?$function@$$A6AXPEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@Z@std@@@Z) referenced in function "private: virtual void __cdecl EventTest_TestEventFiresAndPassesArgs_Test::TestBody(void)" (?TestBody@EventTest_TestEventFiresAndPassesArgs_Test@@EEAAXXZ)
2>EventTest.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl CompanyName::Utils::Event<class std::basic_string<char,struct="" std::char_traits<char="">,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> > >::Invoke(class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> > const *,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> >)const " (__imp_?Invoke@?$Event@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@Utils@CompanyName@@QEBAXPEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V45@@Z) referenced in function "private: virtual void __cdecl EventTest_TestEventFiresAndPassesArgs_Test::TestBody(void)" (?TestBody@EventTest_TestEventFiresAndPassesArgs_Test@@EEAAXXZ)
2>EventTest.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl CompanyName::Utils::Event<class std::basic_string<char,struct="" std::char_traits<char="">,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> > >::Event<class std::basic_string<char,struct="" std::char_traits<char="">,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> > >(void)" (__imp_??0?$Event@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@Utils@CompanyName@@QEAA@XZ) referenced in function "private: virtual void __cdecl EventTest_TestEventFiresAndPassesArgs_Test::TestBody(void)" (?TestBody@EventTest_TestEventFiresAndPassesArgs_Test@@EEAAXXZ)
2>EventTest.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl CompanyName::Utils::Event<class std::basic_string<char,struct="" std::char_traits<char="">,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> > >::~Event<class std::basic_string<char,struct="" std::char_traits<char="">,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> > >(void)" (__imp_??1?$Event@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@Utils@CompanyName@@QEAA@XZ) referenced in function "private: virtual void __cdecl EventTest_TestEventFiresAndPassesArgs_Test::TestBody(void)" (?TestBody@EventTest_TestEventFiresAndPassesArgs_Test@@EEAAXXZ)
2>..\runCoreUnitTests.exe : fatal error LNK1120: 4 unresolved externals
</char></char,struct></char></class></char></char,struct></char></class></char></char,struct></char></class></char></char,struct></char></class></char></char,struct></char></char,struct></char></char,struct></char></class></char></char,struct></char></void></char></char,struct></char></class></char></char,struct></char></class>

Любые идеи, что я делаю неправильно здесь?

1 ответ

Для создания библиотеки DLL нужны функции, которые нужно экспортировать с помощью __declspec(dllexport).

Вы можете использовать такие функции из другой DLL, объявив эти функции, используя __declspec(dllimport).

Они отлично работают для регулярных функций.

Однако для шаблонов классов и шаблонов функций шаблоны создаются по мере необходимости. Они не экспортируются в DLL, в которой они определены. Следовательно, они также не могут быть импортированы из DLL. По этой причине вы не используете __declspec(dllexport) или __declspec(dllimport) с шаблонами классов и шаблонами функций.

licensed under cc by-sa 3.0 with attribution.