Domanda

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

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

se io dichiaro serviceMatchinCallback come statica allora funziona, ma io non voglio che sia statica. C'è un modo per passare una funzione di callback non statico?

Grazie

È stato utile?

Soluzione

Si potrebbe tenerlo statica, ma utilizzare l'userdata per memorizzare il puntatore this in aggiunta a qualsiasi altro userdata che vuoi (da loro imballaggio in una struttura, per esempio) e quindi chiamare un callback specifica per oggetto dalla versione statica chiamando this->someCallback (dove this è il puntatore memorizzato nel userdata, ovviamente).

Altri suggerimenti

Il prototipo di IOServiceMatchingCallback non è compatibile con un metodo di classe non statico (e tecnicamente è non è compatibile con un metodo di classe statica o ), in modo che non si sta per essere in grado di utilizzare tale.

Ma per fortuna IOServiceAddMatchingNotification supporta un puntatore di contesto (o come lo chiamano, un REFCON) che vi permetterà di creare un thunk che non si basa su dati globali.

È necessario definire una funzione di callback con leveraggio compatibile (cioè extern "C"). Questa funzione lanciare la vostra REFCON al puntatore oggetto e poi inoltrare la chiamata al metodo di istanza:

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

Poi, quando si chiama IOServiceAddMatchingNotification, assicurarsi di passare un puntatore all'oggetto per REFCON (qui sto assumendo si chiama IOServiceAddMatchingNotification da una funzione membro e si dispone di un questo puntatore):

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

Non direttamente.

Il puntatore a funzione non statica (noto come un puntatore a funzione membro) ha un nascosto 'questo' parametro in modo che i tipi non corrispondono. La funzione statica non ha puntatore 'this'.

Per aggirare il problema, è necessario essere in grado di passare in un dato utente che è il puntatore 'this' dell'oggetto che si desidera utilizzare come un callback. Quindi, specificare un membro statico che viene passato i dati utente, lo converte in un puntatore all'oggetto classe e invita il membro non static il.

Guardando il codice che hai postato, è difficile dire se v'è un oggetto di dati utente, forse l'ultimo, ma = un parametro.

No, un membro non statica si aspetterebbe un oggetto, e il chiamante (call-sostenitore) non ha e non fornirà uno.

No. metodi non statici bisogno di un oggetto su cui operare. Se si dovesse passare solo il metodo che si sarebbe anche bisogno di qualche modo per dire la funzione di quale oggetto per chiamare il metodo su.

Una funzione non static ha un parametro this implicita, e quindi avrebbe la firma sbagliato per la richiamata.

Siamo spiacenti, un modo semplice per evitare l'isola salto.

se metti questa riga nel costruttore (o in qualsiasi metodo di istanza) allora si dovrebbe essere in grado di fare this.instanceMethod () per fare riferimento al metodo di istanza.

Modifica Ho appena notato che si sta utilizzando l'API IOKit spazio utente, non il lato kext, il che rende questo post irrilevante.


Supponendo che si sta lavorando all'interno del kernel OS X, in realtà si può fare questo. È possibile utilizzare il OSMemberFunctionCast macro per convertire un puntatore funzione membro un puntatore a funzione C normale, notano che dovrebbe essere chiamato con il primo argomento che punta a un'istanza della classe, ad es.

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

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             mycb,
             &myclassinstance,
             &enumerator);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top