2017-05-09 3 views
0

Ich schreibe einen DLL-Wrapper zu einer C++ Builder VCL-Klasse. Dies ist ein äußerst vereinfachtes Beispiel des Problems:Verwenden Sie ein Nicht-Klassenmitglied als Ereignishandler

typedef void __fastcall (__closure *TMyEvent)(int index); 

class TMyClass { 
    public: 
    TMyEvent OnMyEvent; 
}; 

void __fastcall myEventHandler(int index) { } 

TMyClass myClass; 
myClass.OnMyEvent = myEventHandler; 

... und hier ist das Problem: Normalerweise myEventHandler innerhalb einer anderen Klasse definiert ist, aber hier ist es als eine globale Funktion definiert. Wenn ich versuche, myEventHandler zuweisen zu myClass.OnMyEvent ich „Can not void (int) zu TMyEvent konvertieren“

ich die TMyClass Wiederverwendung andere Art von Wrapper zu generieren und müssen die __closeure im typedef so funktioniert es gut mit VCL-Formular-Projekten.

Ist das das Problem (__closure)? Kann ich eine globale Funktion überhaupt als Event-Handler verwenden?

Antwort

2

Die Compilererweiterung __closure ist eine spezielle Art von Klassenmethodenzeiger, der zwei Zeiger enthält - einen Zeiger auf eine Objektinstanz und einen Zeiger auf die Handlermethode. Wenn der __closure ausgeführt wird, übergibt der Compiler den Objektzeiger an den Handler über seine this Parameter. Daher muss der Handler einen this Parameter haben.

Wenn der Handler ein nicht-statisches Element einer Klasse ist, wird die this Zeiger implizit durch den Compiler für Sie, zum Beispiel behandelt:

class TMyEvents { 
public: 
    void __fastcall myEventHandler(int index) { } 
}; 

TMyClass myClass; 
TMyEvents myEvents; 
myClass.OnMyEvent = myEvents.myEventHandler; 

Wenn der Handler ist eine eigenständige Funktion, oder ist ein statische Methode einer Klasse, dann muss der this Zeiger in der Parameterliste explizit angegeben werden. In dieser Situation können Sie die TMethod Struktur verwenden Sie den Handler auf das Ereignis helfen zuweisen, zB:

void __fastcall myEventHandler(void *Data, int index) { } 

TMethod m; 
m.Data = ...; // can be anything you want to pass to the 'Data' parameter 
m.Code = &myEventHandler; 

TMyClass myClass; 
myClass.OnMyEvent = reinterpret_cast<TMyEvent&>(m); 

: das funktioniert nur mit __closure! Versuchen Sie nicht, es mit anderen Arten von Funktionszeigern zu verwenden.

+0

Ich werde es ausprobieren, sobald ich zurück bin ... –

Verwandte Themen