如何将GTK+-2.0的信号、回调处理映射成OOC虚拟成员函数的调用
#ifndef __OBJECT_ORIENTED_C__#define __OBJECT_ORIENTED_C__#ifdef __cplusplusextern "C"{#endif /*========================================================================*/ /*这一区块定义下面用到的一些名字组成宏*/ /*类方法名字拼接*/ #define METHOD(class, method) class##_##method /*类方法的类型的名字拼接*/ #define METHOD_TYPE(class, method) __##class##_##method##_typedef__ /*类的虚函数表结构的名字拼接*/ #define VTBL_STRU_NAME(class) __##class##_v_func_tbl__ /*类的虚函数在虚函数表中的位置的名字拼接*/ #define VTBL_FUNC_PTR_NAME(class, func) __##class##_fp_##func##_offset__ /*类的虚函数表实体的名字拼接*/ #define VTBL_ENTITY_NAME(class) __##class##_vtable_array__ /*类的虚函数表实体初始化函数的名字拼接*/ #define VTBL_ENTITY_INIT_METHOD(class) __##class##_class_vtable_init__ /*类的虚函数表实体是否初始化OK的名字拼接*/ #define VTBL_ENTITY_IS_INIT_FLAG(class) __##class##_class_vtable_is_init__ /*类的虚函数表实体初始化结构变量的名字拼接*/ #define VTBL_ENTITY_INIT_STRU_VAR(class) class##_class_vtable_init_info /*获取类的虚函数表初始化函数的指针*/ #define VTBL_ENTITY_INIT_METHOD_PTR(class) ( VTBL_ENTITY_INIT_STRU_VAR(class) . vtable_init_method) /*========================================================================*/ /*========================================================================*/ /*创建接口*/ #define new(class) METHOD(class, create)() /*释放接口*/ #define delete(class, object) METHOD(class, destory)(object) /*========================================================================*/ /*========================================================================*/ /*类声明的开始宏*/ #define BEGIN_CLASS(class) \ struct class; \
typedefstruct class class; \struct VTBL_STRU_NAME(class); \extern class_vtable_init VTBL_ENTITY_INIT_STRU_VAR(class); \class * METHOD(class, create)(void); \int METHOD(class, constructor)(class* this); \void METHOD(class, destory)(class* this); \int METHOD(class, destructor)(class* this); \struct class /*继承自父类的声明*/ #define INHERITED_PARENT(p_class) \p_class parent/*类中的虚函数声明开始宏*/ #define BEGIN_V_METHOD_DEFINE(class) \ struct VTBL_STRU_NAME(class)/*类继承自父类的虚函数信息*/ #define INHERITED_V_METHOD(p_class) \ structVTBL_STRU_NAME(p_class) parent_vtbl/*单个虚函数声明处*/ #define DEFINE_V_METHOD(ret_type, method) \ret_type (* method )(void* this, ...)/*类中的虚函数声明结束宏*/ #define END_V_METHOD_DEFINE(class) /*根类的对象声明*/ #define ROOT_CLASS_DECLARE(class) \ struct VTBL_STRU_NAME(class) *vbtl;/*类中的声明结束宏*/ #define END_CLASS(class) /*========================================================================*/ /*虚拟函数指针的使用*/ #define GET_V_METHOD_PTR(class, func) \( VTBL_FUNC_PTR_NAME(class, func) )/*定义虚拟函数的类型*/ #define DEFINE_V_METHOD_TYPE(ret_type, class, method) \typedef ret_type (* METHOD_TYPE(class, method) )/*定义虚拟函数的指针: 修改为奇数场景*/ #define DEFINE_V_METHOD_PTR(class, method) \ enum { VTBL_FUNC_PTR_NAME(class, method) =\
((((int )(&((struct VTBL_STRU_NAME(class) *)0)->method )) \/ sizeof(std_func_ptr))<<1) + 1}; \/*定义继承的虚拟函数的指针*/ #define INHERITED_V_METHOD_PTR(class, parent, method) \ enum { VTBL_FUNC_PTR_NAME(class, method) =\
VTBL_FUNC_PTR_NAME(parent, method) }; \/*定义普通的虚拟函数的信息*/ #define DEFINE_V_METHOD_INFO(ret_type, class, method) \DEFINE_V_METHOD_PTR(class, method); \
DEFINE_V_METHOD_TYPE(ret_type,class, method)/*定义继承的虚拟函数的信息*/ #define INHERITED_V_METHOD_INFO(ret_type, class, parent, method) \INHERITED_V_METHOD_PTR(class, parent, method); \
DEFINE_V_METHOD_TYPE(ret_type,class, method)/*定义普通的成员函数的信息*/ #define DEFINE_C_METHOD_INFO(ret_type, class, method) \ extern ret_type METHOD(class, method)/*#define DEFINE_C_METHOD_INFO(ret_type, class, method) \
extern common_func_ptr __##class##_##method##_ptr__; \
typedef ret_type (* VTBL_FUNC_PTR_NAME(class, func) )*/ /*调用对象的虚拟函数*/ #define CALL_V_METHOD(object, method_ptr) \(*(((*( common_func_ptr **) object ))[ ((unsigned int)method_ptr) >> 1]))/*调用对象的虚拟函数:支持参数严格校验*/ #define CALL_V_R_METHOD(object, class, method) \(*(((*( METHOD_TYPE(class, method) **) object ))[ GET_V_METHOD_PTR(class,method) >> 1]))/*调用对象的普通成员函数*/ #define CALL_C_METHOD(object, class, method) \METHOD(class, method)/*#define DECLARE_V_METHOD(ret_type, class, method) \
ret_type METHOD(class, method)
#define DECLARE_C_METHOD(ret_type, class, method) \
common_func_ptr __##class##_##method##_ptr__ = METHOD(class, method); \
ret_type METHOD(class, method)
#define CALL_C_METHOD(ret_type, class, method) \
*(VTBL_FUNC_PTR_NAME(class, method)__##class##_##method##_ptr__)*/ /*========================================================================*/ /*实现类,主要是绑定类的虚拟函数指针*/ #define BEGIN_DECLARE_CLASS_VTABLE(class) \ static std_func_ptr VTBL_ENTITY_NAME(class) [ \sizeof(struct VTBL_STRU_NAME(class) )/sizeof(std_func_ptr)] = {0}; \static char VTBL_ENTITY_IS_INIT_FLAG(class) = 0; \static int VTBL_ENTITY_INIT_METHOD(class) (std_func_ptr *vtbl) \
{ \if (0 != VTBL_ENTITY_IS_INIT_FLAG(class) ) return 1; \if (0 == vtbl) return 0; \do /*继承父类的VTABLE*/ #define INHERITED_VTABLE_INIT(parent) \ if (0 == VTBL_ENTITY_INIT_METHOD_PTR(parent) (vtbl)) return 0 /*继承的虚函数表项初始化*/ #define INHERITED_VTABLE_METHOD_INIT(class, parent, method) \vtbl[((int )(&((struct VTBL_STRU_NAME(parent) * )0)->method )) \/ sizeof(std_func_ptr)] \= (std_func_ptr) METHOD(class, method)/*自身的虚函数表项初始化*/ #define SELF_VTABLE_METHOD_INIT(class, method) \INHERITED_VTABLE_METHOD_INIT(class, class, method)/*实现类的结束宏*/ #define END_DECLARE_CLASS_VTABLE(class) \ while(0); \
VTBL_ENTITY_IS_INIT_FLAG(class) = 1; \return 1; \
} \
class_vtable_init VTBL_ENTITY_INIT_STRU_VAR(class) =\
{ VTBL_ENTITY_INIT_METHOD(class), VTBL_ENTITY_NAME(class)};/*========================================================================*/ /*========================================================================*/ /*类的构造函数,主要提供两个接口:
一个是create,以支持new,
一个是constructor,就是构造并初始化的函数*/ #define BEGIN_CONSTRUCTOR(class, parent) \ extern int METHOD(class, constructor) (class * this); \class* METHOD(class, create) (void) \
{ \return common_create_object(sizeof( class), \
(std_func_ptr) METHOD(class, constructor)); \
} \
\int METHOD(class, constructor) (class * this) \
{ \
VTBL_ENTITY_INIT_METHOD(class) ( VTBL_ENTITY_NAME(class) ); \if (0 != METHOD(parent, constructor) (( parent *)(this))) \return 1; \*(struct VTBL_STRU_NAME(class) **)this =\
(struct VTBL_STRU_NAME(class) *) VTBL_ENTITY_NAME(class) ; \do\/*类构造函数的结束宏*/ #define END_CONSTRUCTOR(class, parent) \ while(0); \return 0; \
}/*根类的父类构造函数为0*/ #define void_constructor(this) (0) /*========================================================================*/ /*========================================================================*/ /*类的析构函数,主要提供两个接口:
一个是destory,以支持delete,
一个是destructor,就是析构函数*/ #define BEGIN_DESTRUCTOR(class, parent) \ extern int METHOD(class, destructor) (class * this); \void METHOD(class, destory) ( class * this) \
{ \
common_destory_object(this, \
(std_func_ptr) METHOD(class, destructor) ); \
} \
\int METHOD(class, destructor) (class * this) \
{ \do\/*类析构函数的结束宏*/ #define END_DESTRUCTOR(class, parent) \ while(0); \if (0 != METHOD(parent, destructor) (( parent *)(this))) \return 1; \return 0; \
}/*根类的父类析构函数为0*/ #define void_destructor(this) (0) /*========================================================================*/typedefint (*std_func_ptr)(void*);
typedefint (*common_func_ptr)(void*, ...);
typedefstruct{int (*vtable_init_method)(std_func_ptr*);
std_func_ptr vtable_array;
}class_vtable_init;void* common_create_object(unsigned intsize, std_func_ptr pCtor);void common_destory_object(void* this, std_func_ptr pDtor);void common_destory_object_non_virtual(void* this, std_func_ptr pDtor);
#ifdef __cplusplus
};#endif /* end of __cplusplus */ #endif
#include "ooc.hoo"#include<stdio.h>#include<stdlib.h> void* common_create_object(unsigned intsize, std_func_ptr pCtor)
{/*分配对象*/ void* object =malloc(size);/*如果分配失败,返回0*/ if (0 == object)return 0;/*调用构造函数*/ if (0 != (*pCtor)(object))
{/*构造函数执行失败,释放对象*/free(object);return 0;
}/*成功,返回对象*/ return object;
}void common_destory_object(void* this, std_func_ptr pDtor)
{/*如果对象为空*/ if (0 == this) return;/*如果存在虚函数表指针*/ if (0 != *(void**)this)
{/*调用虚函数表中的第一个函数指针,默认此函数为析构函数*/ if (0 != (*((*(std_func_ptr**)this)[0]))((void*)this))return;
}else{/*不为空,则调用传入的析构函数指针*/ if (0 != (*pDtor)(this))return;
}/*最后释放对象*/free(this);
}void common_destory_object_non_virtual(void* this, std_func_ptr pDtor)
{if (0 == this) return;if (0 != (*pDtor)(this))return;/*free*/free(this);
}
#ifndef __BASE_OBJECT_STRUCT__#define __BASE_OBJECT_STRUCT__#include<glib.h>#include<glib-object.h>#include"ooc.hoo"#ifdef __cplusplusextern "C"{#endif#ifndef __GNUC__#define SIGNAL_CALLBACK __cdcel #else #define SIGNAL_CALLBACK __attribute__((cdecl)) #endifBEGIN_CLASS(BaseObject)
{/*类自身的数据*/ROOT_CLASS_DECLARE(BaseObject)/*虚拟函数表的定义处*/BEGIN_V_METHOD_DEFINE(BaseObject)
{/*自身的虚函数*/DEFINE_V_METHOD(int, destructor);/*自身的虚函数*/DEFINE_V_METHOD(gulong, setupObject);
}
END_V_METHOD_DEFINE(BaseObject);/*对象的数据*/GObject*x_pObject;
GSList*x_pObjectList;
}
END_CLASS(BaseObject);
typedef gulong (*CommonCallback)(BaseObject* this, GObject*instance, ...);
typedefstructObjectCallbackInfo
{
BaseObject*x_pThis;
CommonCallback x_pCallback;
GObject*x_pWidget;
} ObjectCallbackInfo;
DEFINE_V_METHOD_INFO(int , BaseObject, destructor) (BaseObject* this);
DEFINE_V_METHOD_INFO(gulong , BaseObject, setupObject) (BaseObject* this);
DEFINE_C_METHOD_INFO(gulong , BaseObject, ConnectSignal) (BaseObject* this, gpointer instance, const gchar *detailed_signal, CommonCallback c_handler);
DEFINE_C_METHOD_INFO(gulong , BaseObject, SignalProc) (const ObjectCallbackInfo*lpObject, ...);
#ifdef __cplusplus
};#endif /* end of __cplusplus */ #endif
#include "BaseObject.hoo"gulong METHOD(BaseObject, SignalProc)(const ObjectCallbackInfo*lpObject, ...)
{
va_list pArgList;
gulong ulRetcode;struct reserve_arg { gulong ulReserver[20];} *pstTemp;/*收到信号时,先判断指针*/ if ( (NULL == lpObject) || (NULL == lpObject->x_pCallback ) || (NULL == lpObject->x_pWidget))
{return 0;
}/*取出this指针及成员函数指针*/va_start(pArgList, lpObject);
pstTemp= (struct reserve_arg*)pArgList;/*调用成员函数*/ if ((((unsigned int)lpObject->x_pCallback) & 0x1) == 0x1)
{
printf("enter virtual method branch!\n");
ulRetcode= CALL_V_METHOD ((lpObject->x_pThis), (lpObject->x_pCallback)) (lpObject->x_pThis, lpObject->x_pWidget, *pstTemp);
}else{
ulRetcode= (*(lpObject->x_pCallback))(lpObject->x_pThis, lpObject->x_pWidget, *pstTemp);
}
va_end(pArgList);returnulRetcode;
}
gulong METHOD(BaseObject, ConnectSignal)(BaseObject* this, gpointer instance,const gchar *detailed_signal,
CommonCallback c_handler)
{/*分配存放回调指针的空间*/ObjectCallbackInfo* lpObject = (ObjectCallbackInfo*)g_malloc(sizeof(ObjectCallbackInfo));if (NULL ==lpObject)
{return 0;
}
lpObject->x_pThis = this;
lpObject->x_pCallback =c_handler;
lpObject->x_pWidget = (GObject*)instance;/*将信息保存在slist中*/ this->x_pObjectList = g_slist_append(this->x_pObjectList, lpObject);/*注册信号回调*/ returng_signal_connect_swapped(instance, detailed_signal,
(GCallback)&( METHOD(BaseObject, SignalProc) ),
(gpointer)lpObject);
}
BEGIN_DECLARE_CLASS_VTABLE(BaseObject)
{
SELF_VTABLE_METHOD_INIT(BaseObject, destructor);
}
END_DECLARE_CLASS_VTABLE(BaseObject)
BEGIN_CONSTRUCTOR(BaseObject,void)
{this->x_pObject =NULL;this->x_pObjectList =NULL;
}
END_CONSTRUCTOR(BaseObject,void)
BEGIN_DESTRUCTOR(BaseObject,void)
{/*释放所有分配的ObjectToMemFunc空间*/gpointer lpObj;
GSList* lpTempList = this->x_pObjectList;while (NULL !=lpTempList)
{/*如果非空*/lpObj= g_slist_nth_data(lpTempList, 0);if (NULL !=lpObj)
{
g_free(lpObj);
}
lpTempList=g_slist_next(lpTempList);
}/*删除列表*/ if (NULL != this->x_pObjectList)
{
g_slist_free(this->x_pObjectList);
}
}
END_DESTRUCTOR(BaseObject,void)
#ifndef __UI_TEST_WIN__#define __UI_TEST_WIN__#include"BaseObject.hoo"#include<gtk/gtk.h> /*测试的第一个类*/BEGIN_CLASS(TestDialog)
{/*继承自NullClass*/INHERITED_PARENT(BaseObject);/*虚拟函数表的定义处*/BEGIN_V_METHOD_DEFINE(TestDialog)
{/*继承自NullClass*/INHERITED_V_METHOD(BaseObject);/*自身的虚函数*/DEFINE_V_METHOD(SIGNAL_CALLBACK gulong, OnOk) ;
DEFINE_V_METHOD(SIGNAL_CALLBACK gulong, OnChange) ;
}
END_V_METHOD_DEFINE(TestDialog);/*类自身的数据*/ /*GtkWidget *calendar1;*/GtkWidget*notebook1;
GtkWidget*empty_notebook_page;
GtkWidget*label1;
GtkWidget*label2;
GtkWidget*label3;
}
END_CLASS(TestDialog);
INHERITED_V_METHOD_INFO(int , TestDialog, BaseObject, destructor) (TestDialog* this);
INHERITED_V_METHOD_INFO(int, TestDialog, BaseObject, setupObject) (TestDialog* this);
DEFINE_V_METHOD_INFO(SIGNAL_CALLBACK gulong, TestDialog, OnOk) (TestDialog* this, GtkWidget *notebook1);
DEFINE_V_METHOD_INFO(SIGNAL_CALLBACK gulong, TestDialog, OnChange) (TestDialog* this, GtkWidget *notebook1, GtkNotebookPage *page, guint num);#endif
#include "ui_testwin.hoo"gulong METHOD(TestDialog, OnOk)(TestDialog* this, GtkWidget *notebook1)
{
printf("this : %08x\n", this);
printf("notebook : %08x\n", notebook1);
fflush(stdout);
gtk_main_quit();return 0;
}
gulong METHOD(TestDialog, OnChange)(TestDialog* this, GtkWidget *notebook1, GtkNotebookPage *page, guint num)
{
printf("this : %08x\n", this);
printf("notebook : %08x\n", notebook1);
printf("page : %08x\n", page);
printf("Current Page: %d(%08x)\n", num, num);return 0;
}
gulong METHOD(TestDialog, setupObject)(TestDialog* this)
{
GtkWidget* window1 =gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window1),"window1");
METHOD(BaseObject, ConnectSignal) (this, G_OBJECT (window1), "destroy", (CommonCallback)( GET_V_METHOD_PTR(TestDialog, OnOk )));this->notebook1 =gtk_notebook_new ();
gtk_widget_show (this->notebook1);
gtk_container_add (GTK_CONTAINER (window1),this->notebook1);this->empty_notebook_page = gtk_vbox_new (FALSE, 0);
gtk_widget_show (this->empty_notebook_page);
gtk_container_add (GTK_CONTAINER (this->notebook1), this->empty_notebook_page);this->label1 = gtk_label_new (("label1"));
gtk_widget_show (this->label1);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (this->notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (this->notebook1), 0), this->label1);this->empty_notebook_page = gtk_vbox_new (FALSE, 0);
gtk_widget_show (this->empty_notebook_page);
gtk_container_add (GTK_CONTAINER (this->notebook1), this->empty_notebook_page);this->label2 = gtk_label_new (("label2"));
gtk_widget_show (this->label2);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (this->notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (this->notebook1), 1), this->label2);this->empty_notebook_page = gtk_vbox_new (FALSE, 0);
gtk_widget_show (this->empty_notebook_page);
gtk_container_add (GTK_CONTAINER (this->notebook1), this->empty_notebook_page);this->label3 = gtk_label_new (("label3"));
gtk_widget_show (this->label3);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (this->notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (this->notebook1), 2), this->label3);
METHOD(BaseObject, ConnectSignal) (this, G_OBJECT (this->notebook1), "switch-page", (CommonCallback)(GET_V_METHOD_PTR(TestDialog,OnChange)));/*Store pointers to all widgets, for use by lookup_widget().*/ //GLADE_HOOKUP_OBJECT_NO_REF (window1, window1, "window1");//GLADE_HOOKUP_OBJECT (window1, calendar1, "calendar1"); gtk_widget_show(window1);/*存放对象的基类指针*/ this->parent.x_pObject = (GObject*)window1;return 0;
}
BEGIN_DECLARE_CLASS_VTABLE(TestDialog)
{
INHERITED_VTABLE_INIT(BaseObject);
INHERITED_VTABLE_METHOD_INIT(TestDialog, BaseObject, destructor);
INHERITED_VTABLE_METHOD_INIT(TestDialog, BaseObject, setupObject);
SELF_VTABLE_METHOD_INIT(TestDialog, OnOk);
SELF_VTABLE_METHOD_INIT(TestDialog, OnChange);
}
END_DECLARE_CLASS_VTABLE(TestDialog)
BEGIN_CONSTRUCTOR(TestDialog, BaseObject)
{
}
END_CONSTRUCTOR(TestDialog, BaseObject)
BEGIN_DESTRUCTOR(TestDialog, BaseObject)
{
}
END_DESTRUCTOR(TestClass, BaseObject)int main (int argc, char *argv[])
{
TestDialog* lpDialog =NULL;
gtk_init(&argc, &argv);
lpDialog= new(TestDialog);
CALL_V_R_METHOD(lpDialog, TestDialog, setupObject)(lpDialog);
gtk_main ();
delete(TestDialog, lpDialog);return 0;
}