QT实现(2)

来源:互联网 发布:php 开发教育网站框架 编辑:程序博客网 时间:2024/05/18 00:18

首先看看connect函数的原型,这个函数在QObject类别当中定义:

static bool connect(const QObject *sender, const char *signal,   const QObject *receiver, const char *member, Qt::ConnectionType =Qt::AutoConnection);

由于这个函数是static类型,所以在整个程序当中仅有一个函数,也正因为这样保证了函数的入口唯一性。不过这个函数的调用与这个函数的原型不太一样。

connect(sender, SIGNAL(clicked()),               receiver, SLOT(close()));
# define SLOT(a)     qFlagLocation("1"#a QLOCATION)# define SIGNAL(a)   qFlagLocation("2"#a QLOCATION)

注意这两个宏前面的字符串1和2,这里实际是为了区分signal和slot。

const int flagged_locations_count = 2;static const char* flagged_locations[flagged_locations_count] = {0};const char *qFlagLocation(const char *method){   static int idx = 0;   flagged_locations[idx] = method;   idx = (idx+1) % flagged_locations_count;   return method;}
这里的idx每次累加1,正好将两个字符串放到不同的数组当中。而一个connect刚好同时存在一个signal和slot,这样的话每次connect调用之后都是的idx为0.完整的connect函数实现在qobject.cpp当中。在这个函数第一个调用是QInternal::activateCallbacks。
bool QInternal::activateCallbacks(Callback cb, void **parameters){   QInternal_CallBackTable *cbt = global_callback_table();   if (cbt && cb < cbt->callbacks.size()) {       QList<qInternalCallback> callbacks = cbt->callbacks[cb];       bool ret = false;       for (int i=0; i<callbacks.size(); ++i)           ret |= (callbacks.at(i))(para
typedef bool (*qInternalCallback)(void **);

meters); return ret; } return false;}

看起来这里首先调用一个函数,实际这个函数式利用宏定义出来的。
struct QInternal_CallBackTable {    QVector<QList<qInternalCallback> > callbacks;};Q_GLOBAL_STATIC(QInternal_CallBackTable, global_callback_table)
#define Q_GLOBAL_STATIC(TYPE, NAME)                                           \    static TYPE *NAME()                                                       \    {                                                                         \        Q_GLOBAL_STATIC_INIT(TYPE, _StaticVar_);                              \        if (!this__StaticVar_.pointer && !this__StaticVar_.destroyed) {       \            TYPE *x = new TYPE;                                               \            if (!this__StaticVar_.pointer.testAndSetOrdered(0, x))            \                delete x;                                                     \            else                                                              \                static QGlobalStaticDeleter<TYPE > cleanup(this__StaticVar_); \        }                                                                     \        return this__StaticVar_.pointer;                                      \    }
#define Q_GLOBAL_STATIC_INIT(TYPE, NAME)                                      \        static QGlobalStatic<TYPE > this_ ## NAME                             \                            = { Q_BASIC_ATOMIC_INITIALIZER(0), false }
整个宏展开就是为了返回一个指针,由于最后的QGlobalStatic是一个全局的静态变量。所以这个宏并不是什么都没做,而是对这个全局指针进行检查,如果这个指针不存在,那么就将他给new出来,同时设置出师化值为0,如果初始化不成功,直接delete掉,反之为这个全局变量定义一个清理类别。因为析构函数和构造函数调用的顺序刚好相反,所以这里刚好先将指针给清理掉,然后再调用QGlobalStatic的析构函数。

typedef bool (*qInternalCallback)(void **);
这些回调函数在系统刚刚初始化的时候被设置。回调函数的原型如上面所示。到这里整个函数的流程很明了了,只不过借助了List和Vector的管理。整个函数在qglobal.cpp当中实现。

回到connect函数,接下来是对参数进行检查,当参数有问题就打印调试错误。

static bool check_signal_macro(const QObject *sender, const char *signal,                               const char *func, const char *op){   int sigcode = extract_code(signal);   if (sigcode != QSIGNAL_CODE) {       if (sigcode == QSLOT_CODE)           qWarning("Object::%s: Attempt to %s non-signal %s::%s",                    func, op, sender->metaObject()->className(), signal+1);       else           qWarning("Object::%s: Use the SIGNAL macro to %s %s::%s",                    func, op, sender->metaObject()->className(), signal);       return false;   }   return true;}static int extract_code(const char *member){   return (((int)(*member) - '0') & 0x3);}首先减掉字符0的以得到数值,然后和0x03相与分理出数值1或者2;而这个正好是在宏里面添加的前缀标识符。函数里面的两个宏名称也不言而喻了,很明显,一个是数值1,另一个而是数值2.

由于不能多个信号对应一个槽,所以这里要检测是否存在这种情况。

int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,const char *signal,bool normalizeStringData){   int i = indexOfMethodRelative<MethodSignal>(baseObject, signal, normalizeStringData);   const QMetaObject *m = *baseObject;   if (i >= 0 && m && m->d.superdata) {       int conflict = m->d.superdata->indexOfMethod(signal);       if (conflict >= 0)           qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",                    signal, m->d.superdata->d.stringdata, m->d.stringdata);   }   return i;}template<int MethodType>static inline int indexOfMethodRelative(const QMetaObject **baseObject,                                       const char *method,                                       bool normalizeStringData){   for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {       int i = (MethodType == MethodSignal && priv(m->d.data)->revision >= 4)               ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1);       const int end = (MethodType == MethodSlot && priv(m->d.data)->revision >= 4)                       ? (priv(m->d.data)->signalCount) : 0;       if (!normalizeStringData) {           for (; i >= end; --i) {               const char *stringdata = m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5*i];               if (method[0] == stringdata[0] && strcmp(method + 1, stringdata + 1) == 0) {                   *baseObject = m;                   return i;               }           }       } else if (priv(m->d.data)->revision < 5) {           for (; i >= end; --i) {               const char *stringdata = (m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5 * i]);               const QByteArray normalizedSignature = QMetaObject::normalizedSignature(stringdata);               if (normalizedSignature == method) {                   *baseObject = m;                   return i;               }           }       }   }   return -1;}static inline const QMetaObjectPrivate *priv(const uint* data){ return reinterpret_cast<const QMetaObjectPrivate*>(data); }

                                             
0 0
原创粉丝点击