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


    想将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>
    10 inline FuncPt1 Func_Cast(FuncPt2 pt1)
    11 {
    12     union __TranPt1ToPt2
    13     {
    14         FuncPt2 pointer2;
    15         FuncPt1 pointer1;
    16     } __Tran = {pt1};
    17     return __Tran.pointer1;
    18 }
    19 #endif
    20 
    21 #ifndef __GNUC__
    22 #define SIGNAL_CALLBACK __cdcel
    23 #else
    24 #define SIGNAL_CALLBACK __attribute__((cdecl))
    25 #endif
    26 
    27 class BaseObject
    28 {
    29 public:
    30     BaseObject();
    31     virtual ~BaseObject();
    32 
    33     /* 创建对象并绑定信号的接口 */
    34     virtual gulong setupObject() = 0;
    35 
    36 protected:
    37     typedef gulong (BaseObject::*CommonCallback)(GObject*instance, ...);
    38 
    39     typedef struct tagOBJ_CALLBACK
    40     {
    41         BaseObject*     x_pThis;
    42         CommonCallback  x_pCallback;
    43         GObject*        x_pWidget;
    44     } ObjectCallbackInfo;
    45 
    46     GObject*    x_pObject;
    47 
    48     gulong ConnectSignal(gpointer instance, const gchar *detailed_signal, CommonCallback c_handler);
    49 
    50 private:
    51     GSList* x_pObjectList;
    52 
    53     static gulong SignalProc(const ObjectCallbackInfo* lpObject, ...);
    54 };
    55 
    56 #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()
    10 {
    11     /* 释放所有分配的ObjectToMemFunc空间 */
    12     gpointer lpObj;
    13     GSList* lpTempList = x_pObjectList;
    14     while (NULL != lpTempList)
    15     {
    16         /* 如果非空 */
    17         lpObj = g_slist_nth_data(lpTempList, 0);
    18         if (NULL != lpObj)
    19         {
    20             g_free(lpObj);
    21         }
    22     
    23         lpTempList = g_slist_next(lpTempList);
    24     }
    25     /* 删除列表 */
    26     if (NULL != x_pObjectList)
    27     {
    28         g_slist_free(x_pObjectList);
    29     }
    30 }
    31 
    32 gulong BaseObject::ConnectSignal(gpointer instance, 
    33                                  const gchar *detailed_signal,
    34                                  CommonCallback c_handler)
    35 {
    36     /* 分配存放回调指针的空间 */
    37     ObjectCallbackInfo* lpObject = (ObjectCallbackInfo*)g_malloc(sizeof(ObjectCallbackInfo));
    38     if (NULL == lpObject)
    39     {
    40         return 0;
    41     }
    42     lpObject->x_pThis     = this;
    43     lpObject->x_pCallback = c_handler;
    44     lpObject->x_pWidget   = (GObject*)instance;
    45     /* 将信息保存在slist中 */
    46     x_pObjectList = g_slist_append(x_pObjectList, lpObject);
    47 
    48     /* 注册信号回调 */
    49     return g_signal_connect_swapped(instance, detailed_signal, 
    50                                    (GCallback)&(BaseObject::SignalProc), (gpointer)lpObject);
    51 }
    52 
    53 gulong BaseObject::SignalProc(const ObjectCallbackInfo* lpObject, ...)
    54 {
    55     va_list pArgList;
    56     gulong ulRetcode;
    57     struct reserve_arg { gulong ulReserver[20];} *pstTemp;
    58     BaseObject* lpThis;
    59     CommonCallback pCallBack;
    60 
    61     /* 收到信号时,先判断指针 */
    62     if ( (NULL == lpObject) || (NULL == lpObject->x_pCallback ) || (NULL == lpObject->x_pWidget))
    63     {
    64         return 0;
    65     }
    66     /* 取出this指针及成员函数指针 */
    67     va_start(pArgList, lpObject);
    68     pstTemp = (struct reserve_arg*)pArgList;
    69     lpThis = lpObject->x_pThis;
    70     pCallBack = lpObject->x_pCallback;
    71     
    72     /* 调用成员函数 */
    73     ulRetcode = (lpThis ->*pCallBack)(lpObject->x_pWidget, *pstTemp);
    74     
    75     va_end(pArgList);
    76     
    77     return ulRetcode;
    78 }

     使用几个关键技术点:

    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,那么在生成调用代码时,应该就是能够支持虚拟继承的成员函数指针调用 -- 未验证

  • 相关阅读:
    Newbe.Claptrap 框架入门,第三步 —— 定义 Claptrap,管理商品库存
    Hudi on Flink在顺丰的实践应用
    Kafka监控必备——Kafka-Eagle 2.0.2正式发布
    如何将炫酷的报表直接截图发送邮件——在Superset 0.37使用Schedule Email功能
    突发!美商务部宣布封禁微信,TikTok——面对科技封锁,如何应对
    离线安装Superset 0.37
    Windows系统快速安装Superset 0.37
    Superset 0.37 发布——颜值最高的数据可视化平台
    Hive查看,删除分区
    超详细,Windows系统搭建Flink官方练习环境
  • 原文地址:https://www.cnblogs.com/eaglexmw/p/3054876.html
Copyright © 2020-2023  润新知