您的位置:首页 > 其它

如何将GTK+-2.0的信号、回调处理映射成类成员函数的调用

2013-05-02 16:27 501 查看
想将GTK+-2.0的信号、回调处理映射成类成员函数,然后我们就可以很简单的

将一个个GTK+2.0中的构件映射成类了,其实就是避开GTKMM那么复杂的东东。

1 #ifndef __BASE_OBJECT_CLASS__
2 #define __BASE_OBJECT_CLASS__
3
4 #include <glib.h>
5 #include <glib-object.h>
6
7 #if 0
8 //函数指针转换,可以把一种类型的数据直接转换成第二种类型的数据
9 template <class FuncPt1, class FuncPt2>
inline FuncPt1 Func_Cast(FuncPt2 pt1)
{
union __TranPt1ToPt2
{
FuncPt2 pointer2;
FuncPt1 pointer1;
} __Tran = {pt1};
return __Tran.pointer1;
}
#endif

#ifndef __GNUC__
#define SIGNAL_CALLBACK __cdcel
#else
#define SIGNAL_CALLBACK __attribute__((cdecl))
#endif

class BaseObject
{
public:
BaseObject();
virtual ~BaseObject();

/* 创建对象并绑定信号的接口 */
virtual gulong setupObject() = 0;

protected:
typedef gulong (BaseObject::*CommonCallback)(GObject*instance, ...);

typedef struct tagOBJ_CALLBACK
{
BaseObject* x_pThis;
CommonCallback x_pCallback;
GObject* x_pWidget;
} ObjectCallbackInfo;

GObject* x_pObject;

gulong ConnectSignal(gpointer instance, const gchar *detailed_signal, CommonCallback c_handler);

private:
GSList* x_pObjectList;

static gulong SignalProc(const ObjectCallbackInfo* lpObject, ...);
};

#endif

1 #include "BaseObject.hpp"
2 #include <stdarg.h>
3 #include <stdio.h>
4
5 BaseObject::BaseObject():x_pObject(NULL),x_pObjectList(NULL)
6 {
7 }
8
9 BaseObject::~BaseObject()
{
/* 释放所有分配的ObjectToMemFunc空间 */
gpointer lpObj;
GSList* lpTempList = 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 != x_pObjectList)
{
g_slist_free(x_pObjectList);
}
}

gulong BaseObject::ConnectSignal(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中 */
x_pObjectList = g_slist_append(x_pObjectList, lpObject);

/* 注册信号回调 */
return g_signal_connect_swapped(instance, detailed_signal,
(GCallback)&(BaseObject::SignalProc), (gpointer)lpObject);
}

gulong BaseObject::SignalProc(const ObjectCallbackInfo* lpObject, ...)
{
va_list pArgList;
gulong ulRetcode;
struct reserve_arg { gulong ulReserver[20];} *pstTemp;
BaseObject* lpThis;
CommonCallback pCallBack;

/* 收到信号时,先判断指针 */
if ( (NULL == lpObject) || (NULL == lpObject->x_pCallback ) || (NULL == lpObject->x_pWidget))
{
return 0;
}
/* 取出this指针及成员函数指针 */
va_start(pArgList, lpObject);
pstTemp = (struct reserve_arg*)pArgList;
lpThis = lpObject->x_pThis;
pCallBack = lpObject->x_pCallback;

/* 调用成员函数 */
ulRetcode = (lpThis ->*pCallBack)(lpObject->x_pWidget, *pstTemp);

va_end(pArgList);

return ulRetcode;
}

使用几个关键技术点:

1.将对象指针、对象的成员函数指针及构件指针保存到对象的成员:一个简单列表中

2.静态成员函数指针作为实际的信号处理接口设置到GTK+-2.0的信号处理中

3.GTK+-2.0的信号处理设置采用g_signal_connect_swapped接口,则静态成员函数第一个参数就是第1步保存的列表指针数据

4.调用成员函数指针时,不考虑成员函数的参数个数,采用默认有20个UINT32的参数作为成员函数的参数,这里要求成员函数必须

是遵守C语言调用规范的,即必须是cdecl,因此声明函数必须为__cdecl

5.使用基类的成员函数指针来调用派生类的成员函数,这种行为已经在标准中声明是未定义的。

6.对于5,单一继承、多继承经验证,在GCC/VC上都通过了。但对于虚拟继承,无法支持,根因还在于虚拟继承的成员函数指针调用

方式完全不相同。

7.对于虚拟继承的成员函数指针调用,实现起来其实也应该不复杂,将BaseObject类进行拆分成Object与BaseObject,然后BaseObject

虚拟继承自Object,那么在生成调用代码时,应该就是能够支持虚拟继承的成员函数指针调用 -- 未验证
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐