AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Callbackfunktion in Klasse

Ein Thema von Eichhoernchen · begonnen am 16. Okt 2006 · letzter Beitrag vom 16. Okt 2006
Antwort Antwort
Seite 1 von 2  1 2      
Eichhoernchen

Registriert seit: 22. Apr 2004
Ort: Hagen
322 Beiträge
 
Turbo Delphi für Win32
 
#1

Callbackfunktion in Klasse

  Alt 16. Okt 2006, 10:01
Hey,
ich bin gerade dabei etwas mit Klassen rumzuexperimentieren, nun hab ich aber ein Problem:
Eine MMSystem Funktion will ne Callbackfunktion haben, soweit ist das ja nicht schwer, dass alles klappt wenn
ich die Callbackfunktion aus der Klasse auslager, wenn ich die Funktion z.B. als protected in die Klasse aufnehme, kann ich sie
nicht als Callbackfunktion nutzen.

Ich zeig euch mal was ich meine:

So klappt es:
Delphi-Quellcode:
procedure midiInCallback(aMidiInHandle: PHMIDIIN; aMsg: Cardinal; aData, aMidiData, aTimeStamp: integer);
begin
{...}
end;

function TSysEx.Open(const device: integer): integer;
begin
  Result := midiInOpen(@fHandle, device, Cardinal(@midiInCallback), device, CALLBACK_FUNCTION);
  {...}
end;
Da das ganze aber eine Klasse werden soll, denke ich sollte die Callbackfunktion auch in die Klasse rein, von daher hab ich das hier versucht:

Delphi-Quellcode:
  TSysEx = class(TObject)
  private
    fHandle: THandle;
    {...}
  protected
    procedure midiInCallback(aMidiInHandle: PHMIDIIN; aMsg: cardinal; aData, aMidiData, aTimeStamp: integer);
  public
    {...}
    function Open(const device: integer): integer;
    {...}
  published
    {...}
  end;


 {...}
procedure TSysEx.midiInCallback(aMidiInHandle: PHMIDIIN; aMsg: cardinal; aData, aMidiData, aTimeStamp: integer);
begin
  {...}
end;


function TSysEx.Open(const device: integer): integer;
begin
  Result := midiInOpen(@fHandle, device, Cardinal(@Self.midiInCallback), device, CALLBACK_FUNCTION);
  {...}
end;
Jetzt gibt der Compiler aber einen Fehler aus: [Pascal Fehler] midi.pas(103): E2036 Variable erforderlich Aber ich versteh nicht, warum das nicht klappt... gibt es da einen Trick?
Die SuFu hab ich schon bemüht, hab auch nen paar Ergebnisse gehabt, da wurde was von asm Tricks gesagt...
aber verstanden hab ich das nicht so ganz, wo genau das Problem bei der Sache liegt und wie es genau zu lösen ist.


Danke für die Antworten

Eichhoernchen
Jan
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#2

Re: Callbackfunktion in Klasse

  Alt 16. Okt 2006, 10:08
Methoden einer Klasse, und das ist deine Callback-Funktion in diesem Fall, haben immer noch den unsichtbaren Self-Parameter in der Parameterliste, deswegen kann eine Methode nicht als Callback-Funktion für eine API-Funktion dienen, weil die Aufrufparameter nicht zusammenpassen.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Eichhoernchen

Registriert seit: 22. Apr 2004
Ort: Hagen
322 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Callbackfunktion in Klasse

  Alt 16. Okt 2006, 10:18
Das ist doch irgendwie blöd...
Dann würden ja alle Instanzen der Klasse die selbe Funktion aufrufen oder?

Wie soll man denn dort dann die Werte an die Klasse weitergeben?

Ich fang gerade erst mit dem Klassen Zeug an, von daher habt Einsicht für eine vielleicht dumme Frage!
Jan
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.611 Beiträge
 
#4

Re: Callbackfunktion in Klasse

  Alt 16. Okt 2006, 10:25
Es geht, ist aber extrem Tricky.

In diesem Thread hier hatte ich damals das gleiche Problem, nämlich ein Callback auf eine Klassenmethode zu setzen. Es ging hier um Service. Unten ist meine Lösung, schau mal nach MakeProcInstance. Das ist das was Du suchst.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
Schrammel

Registriert seit: 21. Jan 2006
Ort: Koblenz
29 Beiträge
 
Delphi 2006 Architect
 
#5

Re: Callbackfunktion in Klasse

  Alt 16. Okt 2006, 10:28
Der Weg ist relativ einfach, wenn die aufgerufene API-Funktion die möglichkeit bietet, einen Benutzer-definierten 32Bit-Wert zu übergeben,der an die Callback-Fukntion weitergerecht wird. Dann kannst Du folgendes machen:

- Auslagern der Callback-Funktion aus der Klasse
- Aufruf der API-Funktion mit der Adresse der zu verwendenden Klasse als Benutzer-definierter Parameter
- In der Callback-Funktion muss dann der übergebene 32-Wert auf einen Zeiger auf den Klassentyp gecastet werden und schon hast Du die die Adresse der Klasseninstanz, mit der Du arbeiten möchtest!

Achtung: Du must ggf. sicherstellen, dass die Callback-Funktion im gleichen Thread aufgerufen wird, in dem auch der Aufruf der API-Funktion erfolgte, ansonsten kann's zu blöden Fehlern kommen. Aber das ist ein anderes Thema.

Gruß

Stefan Schramm
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#6

Re: Callbackfunktion in Klasse

  Alt 16. Okt 2006, 10:36
Zitat von Eichhoernchen:
Das ist doch irgendwie blöd...
Dann würden ja alle Instanzen der Klasse die selbe Funktion aufrufen oder?

Wie soll man denn dort dann die Werte an die Klasse weitergeben?
Nein. Beispiel:

Deine Methode:
foo(bar: Integer); Sieht für Delphi so aus:
foo(Self: TObject; bar: Integer); Der Paramter Self enthält einen Zeiger auf die Klasse, so dass du mit
Self.DoSomething; eine andere Methode der Klasse explizit aufrufen kannst.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.611 Beiträge
 
#7

Re: Callbackfunktion in Klasse

  Alt 16. Okt 2006, 10:41
In meinem Link oben wird genau dieser Self-Parameter dem Funktionsaufruf untergejubelt. Mit MakeProcInstance wird ein ausführbarer Speicherbereich erzeugt, der fest die Methode auf der betreffenden Instanz aufruft indem er diesen Self-Parameter noch zusätzlich in den Stack packt.

Anstelle der Methode selber übergibst Du als Callback-Adresse nun diesen Speicherbereich der den Rest für Dich übernimmt. Wie gesagt sehr tricky, und funktioniert getestet ab D5 bis zur Zeit einschliesslich D2006, aber immerhin tut es da
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#8

Re: Callbackfunktion in Klasse

  Alt 16. Okt 2006, 11:00
Die Frage ist nicht neu
Hier Hilfsfunktionen für cdecl-Callbacks (inklusive Beispiel):
http://www.delphipraxis.net/internal...=387139#387139
Zwei Beiträge weiter die entsprechenden Funktionen für stdcall.
  Mit Zitat antworten Zitat
Eichhoernchen

Registriert seit: 22. Apr 2004
Ort: Hagen
322 Beiträge
 
Turbo Delphi für Win32
 
#9

Re: Callbackfunktion in Klasse

  Alt 16. Okt 2006, 12:53
Zitat von Schrammel:
Der Weg ist relativ einfach, wenn die aufgerufene API-Funktion die möglichkeit bietet, einen Benutzer-definierten 32Bit-Wert zu übergeben,der an die Callback-Fukntion weitergerecht wird. Dann kannst Du folgendes machen:

- Auslagern der Callback-Funktion aus der Klasse
- Aufruf der API-Funktion mit der Adresse der zu verwendenden Klasse als Benutzer-definierter Parameter
- In der Callback-Funktion muss dann der übergebene 32-Wert auf einen Zeiger auf den Klassentyp gecastet werden und schon hast Du die die Adresse der Klasseninstanz, mit der Du arbeiten möchtest!

Achtung: Du must ggf. sicherstellen, dass die Callback-Funktion im gleichen Thread aufgerufen wird, in dem auch der Aufruf der API-Funktion erfolgte, ansonsten kann's zu blöden Fehlern kommen. Aber das ist ein anderes Thema.

Gruß

Stefan Schramm

Die Methode sieht mir am einfachsten aus und ist auch möglich, ich kann nen Parameter mitsenden.
Also ruf ich dann die API-Funktion mit Cardinal(@self) auf als 32Bit wert.
Diesen bekomme ich dann in der Funktion und muss mir die klasse an der Adresse holen, geht das so?:

Delphi-Quellcode:
procedure midiInCallback(aMidiInHandle: PHMIDIIN; aMsg: uint; aData, aMidiData, aTimeStamp: integer); stdcall;
var
  klasse: ^TSysEx;
begin
  klasse := Pointer(aData); //aData ist der Parameter mit der Adresse!
  klasse^.variable := wert;
{...}
end;

//Aufruf:

midiInOpen(@fHandle, device, Cardinal(@midiInCallback), Cardinal(@self), CALLBACK_FUNCTION);
Jan
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#10

Re: Callbackfunktion in Klasse

  Alt 16. Okt 2006, 13:23
Zitat von Eichhoernchen:
geht das so?
Ja.

Du kannst es etwas vereinfachen, da Klassenvariablen ohnehin schon Zeiger sind.
Delphi-Quellcode:
//...
var
  Klasse: TSysEx;
begin
  Klasse := TSysEx(aData);
  Klasse.Variable := Wert;
//...

midiInOpen(..., Integer(Self), ...);
Oder eine Zeile weniger
Delphi-Quellcode:
//...
var
  Klasse: TSysEx absolute aData;
begin
  Klasse.Variable := Wert;
//...

midiInOpen(..., Integer(Self), ...);
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:07 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz