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>;
在一个消费者的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); }
那么链接器的输出是:
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@AEBV?$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
任何想法我在这里做错了吗?
创建DLL时,需要使用__declspec(dllexport)
导出函数。
您可以通过使用__declspec(dllimport)
声明这些函数从另一个DLL使用这些函数。
这些对于常规功能非常有用。
但是,对于类模板和函数模板,模板将根据需要进行实例化。 它们不会被导出到定义它们的DLL中。 因此,它们也不能从DLL中导入。 出于这个原因,您不要使用具有类模板和函数模板的__declspec(dllexport)
或__declspec(dllimport)
。