zoukankan      html  css  js  c++  java
  • 如何将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,那么在生成调用代码时,应该就是能够支持虚拟继承的成员函数指针调用 -- 未验证

  • 相关阅读:
    从零开始——PowerShell应用入门(全例子入门讲解)
    详解C# Tuple VS ValueTuple(元组类 VS 值元组)
    How To Configure VMware fencing using fence_vmware_soap in RHEL High Availability Add On——RHEL Pacemaker中配置STONITH
    DB太大?一键帮你收缩所有DB文件大小(Shrink Files for All Databases in SQL Server)
    SQL Server on Red Hat Enterprise Linux——RHEL上的SQL Server(全截图)
    SQL Server on Ubuntu——Ubuntu上的SQL Server(全截图)
    微软SQL Server认证最新信息(17年5月22日更新),感兴趣的进来看看哟
    Configure Always On Availability Group for SQL Server on RHEL——Red Hat Enterprise Linux上配置SQL Server Always On Availability Group
    3分钟带你了解PowerShell发展历程——PowerShell各版本资料整理
    由Find All References引发的思考。,
  • 原文地址:https://www.cnblogs.com/eaglexmw/p/3054876.html
Copyright © 2011-2022 走看看