Question

 
io_iterator_t enumerator;
kern_return_t   result;
result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             (void *)0x1234,
             & enumerator );

serviceMatchingCallback((void *)0x1234, enumerator);

si je déclare serviceMatchinCallback statique alors il fonctionne, mais je ne veux pas qu'il soit statique. Est-il un moyen de transmettre une fonction de rappel non statique?

Merci

Était-ce utile?

La solution

Vous pouvez le garder statique, mais utilisez le userdata pour stocker le pointeur de this en plus de tout autre userdata que vous voulez (en les emballant dans une structure, par exemple), puis appeler un rappel spécifique à l'objet de la version statique appelant this->someCallback (où this est le pointeur stocké dans le userdata, bien sûr).

Autres conseils

Le prototype IOServiceMatchingCallback n'est pas compatible avec une méthode de classe non statique (et est techniquement pas compatible avec une méthode de classe statique soit ), de sorte que vous n'allez pouvoir l'utiliser.

Mais heureusement IOServiceAddMatchingNotification prend en charge un pointeur de contexte (ou comme ils l'appellent, un Refcon) qui vous permettra de créer un thunk qui ne repose pas sur des données globales.

Vous devez définir un rappel avec lien compatible (à savoir extern « C »). Cette fonction projettera votre Refcon à votre pointeur d'objet, puis transférer l'appel à votre méthode d'instance:

extern "C"
void io_callback(void *refcon, io_iterator_t iterator)
{
    myclass *c = static_cast<myclass *>(refcon);
    c->real_callback(iterator);
}

Ensuite, lorsque vous appelez IOServiceAddMatchingNotification, assurez-vous de passer un pointeur vers votre objet pour Refcon (ici, je suppose que vous appelez IOServiceAddMatchingNotification d'une fonction de membre et vous avez un ce pointeur):

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             this,
             &enumerator );

Pas directement.

Le pointeur de fonction non statique (connue sous le nom d'un pointeur de fonction membre) a un paramètre caché « ce » de sorte que les types ne correspondent pas. La fonction statique n'a pas « ce » pointeur.

Pour contourner ce problème, vous devez être en mesure de passer dans un élément de données d'utilisateur qui est le « ce » pointeur de l'objet que vous souhaitez utiliser comme un rappel. Ensuite, spécifiez un membre statique qui est transmis les données utilisateur, il convertit en un pointeur vers l'objet de classe et appelle le membre non-statique sur elle.

En regardant le code que vous avez posté, il est difficile de dire s'il y a un objet de données d'utilisateur, peut-être la dernière, mais = un paramètre.

Non, un membre non-statique s'attend un objet, et l'appelant (appel Backer) ne dispose pas et ne fournira pas un.

Non. Les méthodes non statiques ont besoin d'un objet pour fonctionner avec. Si vous deviez passer simplement la méthode que vous aurez également besoin d'une certaine façon de dire la fonction quel objet pour appeler la méthode sur.

Une fonction non-static a un paramètre this implicite, et aurait ainsi la mauvaise signature pour le rappel.

Désolé, aucun moyen facile d'éviter l'île de saut.

si vous mettez cette ligne dans votre constructeur (ou dans toute méthode d'instance), alors vous devriez être en mesure de le faire this.instanceMethod () pour se référer à la méthode d'instance.

EDIT Je viens de remarquer que vous utilisez l'espace utilisateur API IOKit, pas du côté kext, ce qui rend ce poste hors de propos.


En supposant que vous travaillez dans le noyau OS X, vous pouvez réellement faire. Vous pouvez utiliser le OSMemberFunctionCast macro pour convertir un pointeur de fonction membre à un pointeur de fonction ordinaire C, ne note qu'il devrait être appelé avec le premier argument en montrant une instance de la classe, par exemple.

IOServiceMatchingCallback mycb = OSMemberFunctionCast(IOServiceMatchingCallback,
    &myclassinstance, &MyClass::cb_method);

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             mycb,
             &myclassinstance,
             &enumerator);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top