Funktionszeiger auf nicht statitsche Klassenmethode
-
Ich kämpfe hier gerade mit einem kleinen Problem. Folgende Aussgangssituation:
Ein Gerätetreiber bietet eine Funktion an die für eine Callbackfunktion einen Funktionszeiger erwartet. Die Funktionaliäten wollte ich in einer Klasse kapseln. Nun würde ich gerne der Funktion eine Instanz meiner Klasse mit zugehöriger Funktion übergeben, so dass sie diese aufrufen kann. Mein Code sah in etwa so aus:typedef void (*NOTIFYPROC) (int i); typedef void (__stdcall*FUNC)(NOTIFYPROC n); class A { FUNC DllFunc; Foo() { //... myProc = (FUNC) GetProcAddress(handle,"DllFunc"); } void Foo() { myProc(this->Notify); } void Notify(int i) { //... } };Ich verstehe, dass es so gar nicht funktionieren kann, da nur über die Adresse der Methode nicht die zugehörige Klasse übermittelt werden kann. Folglich ist mein ganzer Ansatz wohl sinnlos.
Nun suche ich, eine Möglichkeit, dennoch die Funktionalitäten des Treibers in eine Klasse zu kappseln, und habe keine Ahnung wie ich das angehen kann. Der Treiber ist fix, und daran kann ich auch nichts ändern. Dennoch muss dieser der zugehörigen Klasse Nachrichten über die vordefinierten Callbackfunktionen schicken können. Hat mir jemand vielleicht einen Lösungsansatz auf welche Weise man das sinnvoll verwirklichen könnte?
-
Kannst du aufrufspezifische Daten einspeichern, so wie in Win32-Fenster per SetWindowLong einen void-gecasteten this-Zeiger? Dann könntest du die Aufrufe per statischer Methode verteilen. Aber zum Selbstzweck muss man ja nun auch nicht alles in eine Klasse packen, keine Ahnung inwiefern du im konkreten Beispiel davon profitieren würdest.
-
War mein erster Gedanke, aber das kann ich leider nicht, da die Schnittstelle dafür nicht ausgelegt ist.
edit: Profitieren würde ich in dem Falle von dem gesammten Code der darauf aufbaut. Da das ganze die Basis eines neuen Projektes ist, würde ich das Fundament dafür gerne sauber setzten. Es existiert bereits ein anderes Projekt, welches die Schnittstelle direkt implementiert hat, und die Erfaherungen die ich damit gemacht habe, möchte ich ungern ein zweites mal machen. Daher der Wunsch das ganze zu kapseln.
-
Dann wirst du nicht zwischen den Instanzen unterscheiden können. Die einzige Möglichkeit die ich sehe, ist eine Singleton-Klasse. Und dann stellt sich halt auch die Frage, ob's nicht gleich normale Funktionen tun.
-
Alternativ dazu dachte ich auch schon daran das ganze mit einer statischen Funktion un einem Mutex zu lösen, was dann aber logischerweise die Funktion dahingehend einschränken würde, dass bestimmte Aktionen nicht paralell ablaufen können. Das wäre mein Rettungsanker, aber ich hoffe, das jemand eine Idee hat, an die ich bisher nicht dachte.
-
Kannst du mir das genauer erklären? Kann man aus dem Zeitpunkt des Callbackaufrufs schließen, welche Instanz gemeint ist? Und warum hast du mehrere gleichartige Objekte als Kapselungen für einen Treiber?
-
Nun ich dachte daran vor dem Aufruf einer Funktion, die eine Callbackfunktion erwartet die aktuelle Instanz in einem statischen Pointer zu speichern. Die Übergebene Callbackfunktion wäre dann ebenfalls statisch, und würde anhand des Pointers die Aktionen für seine Klasse betrefend auslösen. Nach dem Abschluss (den kriege ich mit anhand bestimmter Parameter), gebe ich den Pointer wieder frei.
Was den Treiber angeht kann ich sagen, dass durch die gleichzeitige Nutzung keine Probleme direkter Art auftreten. Es sind Kommunikationskanäle die aufgebaut werden. Und davon können mehrere zur gleichen Zeit geöffnet werden.
-
Was ist das für ein Treiber, der zwar mehrere Kanäle zulässt, aber bei dem man nicht herausfinden kann, auf welchem was ankam^^
Aber ja, die sache mit dem statischen Memeber ist doch gut, wenn die Callback-Aufrufe nur innerhalb spezifizierter Abschnitte generiert werden.
-
Halbleiter schrieb:
Nun ich dachte daran vor dem Aufruf einer Funktion, die eine Callbackfunktion erwartet die aktuelle Instanz in einem statischen Pointer zu speichern. Die Übergebene Callbackfunktion wäre dann ebenfalls statisch, und würde anhand des Pointers die Aktionen für seine Klasse betrefend auslösen. Nach dem Abschluss (den kriege ich mit anhand bestimmter Parameter), gebe ich den Pointer wieder frei.
So, wie ich das sehe ist das der "einzig" sinnvolle Ansatz. Und ich denke mal, dass du da Probleme vermutest, wenn jetzt das Element, welches ankommt nicht das war, dass es geschickt hat. (Respektive du die Funktion für ein Objekt aufgerufen hast, den Zeiger gespeichert und dann kommt der nächste Funktionsaufruf und dann hast du ein Problem).
Das würde ich dann so lösen, dass du da vorher so etwas, wie einen Stack hast, wo du die Zeiger drauf pusht und dann popst. Irgendetwas muss die die Lib dafür anbieten, sonst macht das mit den mehreren Kanälen wirklich nicht viel Sinn.