2012-12-03 1 views
3

Je suis en train de pirater avec les signaux de Qt et machines à sous, et je suis tombé sur un problème où QMetaType :: invokeMethod ne passera pas correctement des arguments pointeur vers la fente appelée.Qt - en invoquant des fentes qui prennent des pointeurs personnalisés comme arguments

call(QObject *receiver, const char *slot, const QList<QGenericArgument> &args) 
{ 
    const QMetaObject *meta = receiver->metaObject(); 
    bool success = meta->invokeMethod(receiver, slot, 
      args.value(0, QGenericArgument()), 
      args.value(1, QGenericArgument()), 
      args.value(2, QGenericArgument()), 
      ... 
      args.value(9, QGenericArgument())); 
} 

Alors je l'appelle de la manière suivante:

MyReceiver *receiver; 
MyObject *myObject; 

call(receiver, "mySlot", QList<QGenericArgument>() << Q_ARG(MyObject *, myObject)); 

class MyObject : public QObject { ... }. Je fais aussi Q_DECLARE_METATYPE(MyObject *) et qRegisterMetaType<MyObject *>("MyObject *")

Ce qui se passe est que la fente du récepteur est invoquée, mais la valeur de l'argument est toujours 0, peu importe ce que je passe à la call(...) comme Q_ARG

Par curiosité Je regardais dans le fichier MOC généré automatiquement du récepteur, et a constaté que les fentes sont invoquées avec le code suivant:

void MyReceiver::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) 
{ 
    if (_c == QMetaObject::InvokeMetaMethod) { 
     Q_ASSERT(staticMetaObject.cast(_o)); 
     MyReceiver *_t = static_cast<MyReceiver *>(_o); 
     switch (_id) { 
     case 0: _t->mySlot((*reinterpret_cast< MyObject*(*)>(_a[1]))); break; 
     default: ; 
     } 
    } 
} 

Transforme que la valeur de _a[1] porte l'adresse correcte de MyObject *. Mais le reinterpret_cast le transforme en 0.

Maintenant, j'ai les questions suivantes:

1) Comment invoquer une programmation fente et assurez-vous que les arguments de pointeur sont correctement passés à la fente? 2) Que signifie *reinterpret_cast< MyObject*(*)>(_a[1])? Que signifient les parenthèses supplémentaires (*), et comment interpréter ce morceau de code?

+0

Jetez un coup d'oeil dans la macro SLOT(). Cela fait un moment pour moi, mais cela peut répondre à votre question. – dmaij

+0

'invokeMethod' vous permet d'appeler un slot simplement par ses valeurs de nom et d'argument, sans fournir de signature complète. Cela fonctionne bien, mais ne fonctionne pas avec les types d'arguments non standard, au moins pour moi ... –

+0

Cela devrait fonctionner. Votre implémentation call() ne semble pas réellement transmettre les arguments (ou est-ce juste votre exemple de code qui est incorrect?). Cela fonctionne-t-il si vous appelez QMetaObject :: invokeMethod directement? _a [1] est un pointeur vers un pointeur, d'où le (*) dans le reinterpret_cast. –

Répondre

0

Ok, je pense que je me suis dit pourquoi il ne fonctionne pas ... Q_ARG ne créera un pointeur sur mon pointeur et stocker l'ancien. Je ne l'ai pas mentionné que la fonction call faisait partie de l'appel Task destiné à invoquer une fente plus tard - lorsque les valeurs enveloppées dans Q_ARG sont déjà hors de portée. Fondamentalement, Q_ARG ne conserve qu'une faible référence à l'objet argument.

Questions connexes