如何将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,那么在生成调用代码时,应该就是能够支持虚拟继承的成员函数指针调用 -- 未验证
将一个个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,那么在生成调用代码时,应该就是能够支持虚拟继承的成员函数指针调用 -- 未验证
相关文章推荐
- 如何将GTK+-2.0的信号、回调处理映射成类成员函数的调用--VC中测试(单类继承)
- 如何将GTK+-2.0的信号、回调处理映射成类成员函数的调用--示例
- 如何将GTK+-2.0的信号、回调处理映射成类成员函数的调用--VC中测试(虚拟继承类及多继承)
- 如何将GTK+-2.0的信号、回调处理映射成OOC虚拟成员函数的调用
- Redis系列(二)---如何接受客户端请求并调用处理函数
- Linux 多线程应用中如何编写安全的信号处理函数
- Linux 多线程应用中如何编写安全的信号处理函数(转载IBM)
- Linux 多线程应用中如何编写安全的信号处理函数
- 如何让API回调你的VC类成员函数而不是静态函数
- VC多线程中全局函数如何调用对话框类成员变量及成员函数
- 高级事件和信号处理@GTK+ 2.0 中文教程连载
- GLib实用程序和错误处理函数@GTK+ 2.0 中文教程连载
- 关于Qt 静态成员函数调用信号
- Linux 多线程应用中如何编写安全的信号处理函数
- 基于对话框的MFC应用程序,在“工程名.cpp”文件里如何调用“工程名+Dlg.cpp”文件里“工程名+Dlg”类的public成员函数?
- 静态成员函数如何调用非静态成员变量
- 在VC6.0中创建和使用静态链接库&amp;amp;&amp;amp;C如何调用C++ 成员函数
- signal signal函数每次设置具体的信号处理函数(非SIG_IGN)只能生效一次,多次调用需要调用时在加类似监听的方法!!! 最好用sigaction
- 如何让API回调你的VC类成员函数而不是静态函数
- 10_5 在信号处理函数中调用非可重入函数getpwnam。