Frage

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

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

, wenn ich serviceMatchinCallback als statisch deklarieren dann funktioniert es, aber ich will sie nicht statisch sein. Gibt es eine Möglichkeit, ihm eine nicht-statische Callback-Funktion übergeben?

Danke

War es hilfreich?

Lösung

Sie könnten es statisch halten, sondern verwenden Sie die Benutzerdaten den this Zeiger zusätzlich zu speichern, was auch immer andere Benutzerdaten Sie wollen (indem sie in eine Struktur, zum Beispiel Verpackung) und rufen Sie dann einen objektspezifische Rückruf von der statischen Version von Aufruf this->someCallback (wo this den Zeiger in den Benutzerdaten, natürlich gespeichert ist).

Andere Tipps

Der Prototyp für IOServiceMatchingCallback nicht kompatibel mit einer nicht-statischen Klassenmethode ist (und technisch ist nicht mit einer statischen Klassenmethode entweder ) kompatibel, so dass Sie nicht, dass verwenden gehen können.

Aber zum Glück IOServiceAddMatchingNotification unterstützt einen Kontextzeiger (oder wie sie es nennen, ein REFCON), die Ihnen eine Thunk erstellen können, die nicht auf globale Daten angewiesen ist.

Sie benötigen einen Rückruf mit kompatibeler Verknüpfung definieren (das heißt extern „C“). Diese Funktion wird Ihre REFCON auf Ihre Objektzeiger gegossen und dann nach vorne um den Anruf zu Ihrer Instanz Methode:

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

Wenn Sie dann IOServiceAddMatchingNotification nennen, stellen Sie sicher, einen Zeiger auf das Objekt zu übergeben für REFCON (hier ich nehme an, Sie IOServiceAddMatchingNotification von einem Mitglied-Funktion aufrufen, und Sie haben einen diesen Zeiger):

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

Nicht direkt.

Die nicht-statische Funktion Zeiger (als Mitglied Funktionszeiger genannt) hat einen versteckten ‚diese‘ Parameter so die Typen nicht übereinstimmen. Die statische Funktion hat keinen ‚diesen‘ Zeiger.

Um dies zu umgehen, müssen Sie in der Lage sein, in einem Benutzerdatenelement zu übergeben, die die ‚this‘ Zeiger des Objekts, das Sie als Rückruf verwenden mögen. Dann wird ein statisches Element angeben, dass die Benutzerdaten übergeben wird, wandelt es in einen Zeiger auf das Klassenobjekt und ruft das nicht-statische Element darauf.

Mit Blick auf den Code, den Sie geschrieben haben, ist es schwer zu sagen, ob es ein Nutzdatenobjekt ist, möglicherweise die zuletzt aber = ein Parameter.

Nein, ein nicht-statisches Element würde ein Objekt erwarten, und die Anrufer (Call-backer) nicht und wird man nicht liefern.

Nein. Nicht-statische Methoden benötigen, ein Objekt zu arbeiten auf. Wenn Sie die Methode nur passieren, so würde man auch eine gewisse Art und Weise müssen die Funktion, die Aufgabe sagen, auf die Methode aufzurufen.

Eine nicht static Funktion hat einen impliziten this Parameter und damit für den Rückruf die falsche Unterschrift würde.

Zur Zeit keine einfache Möglichkeit, den Sprung Insel zu vermeiden.

Wenn Sie diese Zeile in Ihrem Konstruktor setzen (oder in einer Instanz-Methode), dann sollten Sie in der Lage sein this.instanceMethod zu tun () an die Instanzmethode zu verweisen.

Bearbeiten Ich habe gerade bemerkt Sie den User-Space IOKit API verwenden, nicht die kext Seite, die diesen Beitrag irrelevant macht.


Angenommen, Sie innerhalb des OS X-Kernel arbeiten, können Sie tatsächlich tun. Sie können die OSMemberFunctionCast Makro ein Mitglied Funktionszeiger auf eine Ebene C Funktionszeiger, tun Anmerkung zu konvertieren, dass es mit dem ersten Argument verweist auf eine Instanz der Klasse aufgerufen werden soll, z. B.

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

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             mycb,
             &myclassinstance,
             &enumerator);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top