diff --git a/gObject.cpp b/gObject.cpp index 04f67a42b9e14410753e68e63f7fd387e83a54cd..3cc08f4f9e22febb44fcfcafc609513c1d4c66b4 100644 --- a/gObject.cpp +++ b/gObject.cpp @@ -1,19 +1,22 @@ /* * Copyright (C) 2019 明心 * All rights reserved. - * - * This program is an open-source software; and it is distributed in the hope + * + * This program is an open-source software; and it is distributed in the hope * that it will be useful, but WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * This program is not a free software; so you can not redistribute it(include - * binary form and source code form) without my authorization. And if you - * need use it for any commercial purpose, you should first get commercial - * authorization from me, otherwise there will be your's legal&credit risks. + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. + * This program is not a free software; so you can not redistribute it and/or + * modify it without my authorization. If you only need use it for personal + * study purpose(no redistribution, and without any commercial behavior), + * you should accept and follow the GNU AGPL v3 license, otherwise there + * will be your's credit and legal risks. And if you need use it for any + * commercial purpose, you should first get commercial authorization from + * me, otherwise there will be your's credit and legal risks. * */ -#include +#include "gObject.h" #include #include @@ -21,8 +24,7 @@ struct SenderPair { SenderPair(GObject* _sender, SIGNAL_POINTER(void*) _signal ) :sender(_sender), signal(_signal) - { - } + { } bool operator==(const SenderPair &r ) const { @@ -63,7 +65,7 @@ GObject::~GObject() { destructAsReceiver(); - sigDestroyed(this); + sigDestroyed(); destructAsSender(); delete m_priv; @@ -219,8 +221,15 @@ int GObject::privDisconnect(GObject* sender, SIGNAL_POINTER(void*) signal, GObje slot ); return -1; } + +#ifdef WIN32 + GSlot *vslot = (GSlot*)slot; + SIGNAL_TYPE_ITERATOR(void*) it = std::find_if(signal->begin(), signal->end(), Slot_Is_CppSlot(*vslot)); +#else + SIGNAL_TYPE_ITERATOR(void*) it = std::find_if(signal->begin(), signal->end(), Slot_Is_CppSlot(GSlot(slot, receiver, CPP_SLOT_TYPE))); +#endif // WIN32 + - SIGNAL_TYPE_ITERATOR(void*) it = std::find_if ( signal->begin(), signal->end(), Slot_Is_CppSlot( GSlot( slot, receiver, CPP_SLOT_TYPE) ) ); if(it == signal->end() ) { return -2; @@ -255,7 +264,6 @@ GObject::GObject ( const GObject& /*src*/ ) :m_priv ( new GObjectPrivate ( NULL, "" ) ) { } - void GSlot::operator() ( const GSlot& ) { printf("\n"); diff --git a/gObject.h b/gObject.h index adda6aab426700b7998fc0e0f9567e3e40769eb9..bd9f1a51b1eb40813f1064b11ae25bd43e4c34bb 100644 --- a/gObject.h +++ b/gObject.h @@ -6,10 +6,13 @@ * that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. - * This program is not a free software; so you can not redistribute it(include - * binary form and source code form) without my authorization. And if you - * need use it for any commercial purpose, you should first get commercial - * authorization from me, otherwise there will be your's legal&credit risks. + * This program is not a free software; so you can not redistribute it and/or + * modify it without my authorization. If you only need use it for personal + * study purpose(no redistribution, and without any commercial behavior), + * you should accept and follow the GNU AGPL v3 license, otherwise there + * will be your's credit and legal risks. And if you need use it for any + * commercial purpose, you should first get commercial authorization from + * me, otherwise there will be your's credit and legal risks. * */ @@ -25,6 +28,7 @@ class GObjectPrivate; class GObject; #define slots +#define signals public enum E_SLOT_TYPE { @@ -32,8 +36,10 @@ enum E_SLOT_TYPE CPP_SLOT_TYPE, }; -template -class GSlotAPI +template +class GSlotAPI; +template +class GSlotAPI { public: E_SLOT_TYPE type() const @@ -71,44 +77,36 @@ private: E_SLOT_TYPE m_type; }; -template -class GSlotC : public GSlotAPI -{ -private: - typedef void ( *SlotFuncType ) ( Args... ); - -public: - GSlotC ( SlotFuncType slot ) - : GSlotAPI( (void*)slot ) - { - } - virtual ~GSlotC() {} - -public: - void operator() ( Args&... args ) - { - ( (SlotFuncType)GSlotAPI::m_slot) ( args... ); - } -}; - -template -class GSlotCpp : public GSlotAPI +template +class GSlotCpp; +template +class GSlotCpp : public GSlotAPI { public: typedef void ( Receiver::*SlotFuncType ) ( Args... ); - GSlotCpp ( Receiver* r, SlotFuncType slot ) - : GSlotAPI( (void*)slot, (GObject*)r, CPP_SLOT_TYPE), - m_class_slot(slot) - { - } +#ifdef WIN32 + GSlotCpp(Receiver* r, SlotFuncType slot) + : GSlotAPI((void*)&slot, (GObject*)r, CPP_SLOT_TYPE), + m_class_slot(slot) + { + } +#else + GSlotCpp(Receiver* r, SlotFuncType slot) + : GSlotAPI((void*)slot, (GObject*)r, CPP_SLOT_TYPE), + m_class_slot(slot) + { + } +#endif // WIN32 + + virtual ~GSlotCpp() {} public: void operator() ( Args&... args ) { - ( ( (Receiver*)GSlotAPI::m_receiver)->*m_class_slot ) ( args... ); + ( ( (Receiver*)GSlotAPI::m_receiver)->*m_class_slot ) ( args... ); } private: @@ -117,16 +115,18 @@ private: /** * @class GSignal - * @brief GSignal类用来定义信号,所述信号的函数类型为void (*)(Args...)。\n - * 比如:GSignal intSig;//定义一个函数类型为void intSig(int); - * 比如:GSignal ifSig;//定义一个函数类型为void ifSig(int, float); + * @brief GSignal 类用来定义信号,所述信号的函数类型为Ret (*)(Args...)。\n + * 比如:GSignal intSig;//定义一个函数类型为void intSig(int); + * 比如:GSignal ifSig;//定义一个函数类型为void ifSig(int, float); * */ -template -class GSignal +template +class GSignal; +template +class GSignal { public: - typedef list* > SlotLstType; + typedef list* > SlotLstType; public: /** @@ -204,13 +204,13 @@ private: #define SIGNAL_POINTER(SlotFuncType) list* #define SIGNAL_TYPE_ITERATOR(SlotFuncType) list::iterator -#define signals public class GObject { signals: - GSignal sigDestroyed; - + ///当对象被析构时,会发射此信号 + GSignal sigDestroyed; + private: GObjectPrivate *m_priv; @@ -228,12 +228,12 @@ public: * @param sender 指向发射者的指针 * @param signal 指向信号的引用。 * @param receiver 指向接收者的指针 - * @param slot 指向槽函数的指针 + * @param SlotFunc 指向槽函数的指针 * * @return 0代表成功;非0代表失败 */ template - static int connect ( GObject* sender, GSignal& signal, Receiver* receiver, void ( Receiver::*SlotFunc ) ( Args... ) ); + static int connect ( GObject* sender, GSignal& signal, Receiver* receiver, void ( Receiver::*SlotFunc ) ( Args... ) ); /** * @brief 将信号和槽断开连接。\n @@ -243,14 +243,25 @@ public: * @param sender 指向发射者的指针 * @param signal 指向信号的引用。 * @param receiver 指向接收者的指针 - * @param slot 指向槽函数的指针 + * @param SlotFunc 指向槽函数的指针 * * @return 0代表成功;非0代表失败 */ template - static int disconnect ( GObject* sender, GSignal& signal, Receiver* receiver, void ( Receiver::*SlotFunc ) ( Args... ) ); + static int disconnect ( GObject* sender, GSignal& signal, Receiver* receiver, void ( Receiver::*SlotFunc ) ( Args... ) ); + /** + * @brief 获取对象名称 + * + * @return const char* + */ const char *name() const; + + /** + * @brief 获取对象的parent + * + * @return GObject* + */ GObject *parent() const; @@ -266,9 +277,9 @@ private: }; template -int GObject::connect ( GObject* sender, GSignal& signal, Receiver* receiver, void ( Receiver::*SlotFunc ) ( Args... ) ) +int GObject::connect ( GObject* sender, GSignal& signal, Receiver* receiver, void ( Receiver::*SlotFunc ) ( Args... ) ) { - GSlotCpp *vslot = new GSlotCpp(receiver, SlotFunc); + GSlotCpp *vslot = new GSlotCpp(receiver, SlotFunc); int ret = privConnect(sender, reinterpret_cast(&(signal._slotLst)), (GObject*)receiver, (void*)vslot); if(0 != ret) { @@ -278,9 +289,19 @@ int GObject::connect ( GObject* sender, GSignal& signal, Receiver* rec } template -int GObject::disconnect ( GObject* sender, GSignal& signal, Receiver* receiver, void ( Receiver::*SlotFunc ) ( Args... ) ) +int GObject::disconnect ( GObject* sender, GSignal& signal, Receiver* receiver, void ( Receiver::*SlotFunc ) ( Args... ) ) { - int ret = privDisconnect(sender, reinterpret_cast(&(signal._slotLst)), (GObject*)receiver, (void*)SlotFunc); +#ifdef WIN32 + GSlotCpp *vslot = new GSlotCpp(receiver, SlotFunc); + int ret = privDisconnect(sender, reinterpret_cast(&(signal._slotLst)), (GObject*)receiver, (void*)vslot); + if (0 != ret) + { + delete vslot; + } +#else + int ret = privDisconnect(sender, reinterpret_cast(&(signal._slotLst)), (GObject*)receiver, (void*)SlotFunc); +#endif // WIN32 + return ret; } diff --git a/main.cpp b/main.cpp index a2b71c688a8e95631f855e46f0cd78024465db7c..7e0794724774535eacb456d4c0b5edad8fafbfc8 100644 --- a/main.cpp +++ b/main.cpp @@ -1,19 +1,22 @@ /* * Copyright (C) 2019 明心 * All rights reserved. - * - * This program is an open-source software; and it is distributed in the hope + * + * This program is an open-source software; and it is distributed in the hope * that it will be useful, but WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * This program is not a free software; so you can not redistribute it(include - * binary form and source code form) without my authorization. And if you - * need use it for any commercial purpose, you should first get commercial - * authorization from me, otherwise there will be your's legal&credit risks. + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. + * This program is not a free software; so you can not redistribute it and/or + * modify it without my authorization. If you only need use it for personal + * study purpose(no redistribution, and without any commercial behavior), + * you should accept and follow the GNU AGPL v3 license, otherwise there + * will be your's credit and legal risks. And if you need use it for any + * commercial purpose, you should first get commercial authorization from + * me, otherwise there will be your's credit and legal risks. * */ -#include +#include "gObject.h" #include /** @@ -23,39 +26,39 @@ * @date 2018-12-27 */ - /** * @class Receiver * @brief Receiver类负责接收信号;并进行业务处理。 - * 通常情况下,一个文件应当只包含一个类,应当由一个名为receiver.cpp/receiver.h的文件来放置Receiver类。 - * 请看main函数中的测试代码,测试代码解释了为什么Receiver需要继承于GObject。 - * */ class Receiver : public GObject { public: Receiver ( ) {} - + public slots: /** * @brief 接收sender发射的selected信号、并进行业务处理 - * + * * @param const string& selected信号传递过来的参数 * @param int selected信号传递过来的参数 * @return void */ - void slotSelected ( const string& str, int idx ) + void slotSelected( const string& str, int idx) { - printf ( "param=[%s, %d]\n", str.c_str(), idx ); + printf("Receiver::slotSelected is called. "); + printf("param=[%s] [%d]\n", str.c_str(), idx); + } + + void slotClicked() + { + printf("Receiver::slotClicked is called\n"); } }; /** * @class Sender * @brief Sender类负责定义信号;并负责在需要时,发射信号。 - * 通常情况下,一个文件应当只包含一个类,应当由一个名为sender.cpp/sender.h的文件来放置Sender类。 - * 请看main函数中的测试代码,测试代码解释了为什么Sender和Receiver需要继承于GObject。 */ class Sender : public GObject { @@ -63,53 +66,57 @@ public: /** * 定义一个名称为selected的信号;该信号接收两个参数,参数类型分别为const string&和int */ - GSignal selected; - + GSignal selected; + + /** + * 定义一个名称为clicked的信号;该信号不接收任何参数 + */ + GSignal clicked; + public: /** * @brief 发射信号 - * + * * @return void */ void notify() { - string a ( "giveda.com" ); - selected ( a, 3 ); - - a = "Hello, Giveda!"; - selected.emit ( a, 6 ); + string a("giveda.com"); + selected(a, 3); + clicked(); } }; -/** - * @brief 通常情况下,main函数应当放置在一个单独文件比如名为main.cpp。 - * main.cpp需要include(依赖)Sender.h和Receiver.h。 - * sender.cpp/sender.h不需要include(依赖)receiver.h。 - * receiver.cpp/receiver.h不需要include(依赖)Sender.h。 - */ -int main ( int /*argc*/, char** /*argv*/ ) +int main(int /*argc*/, char** /*argv*/) { Sender *s = new Sender; s->notify(); - printf ( "before connect\n" ); - + printf("before connect\n"); + Receiver *r = new Receiver; - GObject::connect ( s, s->selected, r, &Receiver::slotSelected ); - printf ( "after connect\n" ); + GObject::connect(s, s->selected, r, &Receiver::slotSelected); + GObject::connect(s, s->clicked, r, &Receiver::slotClicked); + printf("after connect\n"); s->notify(); - - GObject::disconnect ( s, s->selected, r, &Receiver::slotSelected ); - printf ( "after disconnect\n" ); + + GObject::disconnect(s, s->selected, r, &Receiver::slotSelected); + GObject::disconnect(s, s->clicked, r, &Receiver::slotClicked); + printf("after disconnect\n"); s->notify(); - - //请看如下这段代码,这里解释了为什么Sender和Receiver需要继承于GObject。 - //Receiver对象被销毁后,Sender对象与Receiver对象之间的依赖会自动被解除。 - //事实上,如果你根本不在意Receiver被销毁后的情形,那么你当然可以不用继承于GObject。 - printf ( "re-connected, but delete receiver\n" ); - GObject::connect ( s, s->selected, r, &Receiver::slotSelected ); + + printf("re-connected, but delete receiver\n"); + GObject::connect(s, s->selected, r, &Receiver::slotSelected); + GObject::connect(s, s->clicked, r, &Receiver::slotClicked); delete r; s->notify(); + + delete s; +#ifdef WIN32 + system("pause"); + +#endif // WIN32 return 0; } +