![]() |
Tapi Callback Funktion darf nicht in Klasse sein
Hallo,
ich versuche eine vorhandene Anwendung objektorientiert neu zu erstellen, die sich über die Tapi mit unserer Telefonanlage beschäftigt. Ich habe als Objekte Lines, Devices und Calls erstellt und möchte nun als letztes ein Objekt erstellen, dass diese anderen Objekte verwalten kann, wenn man so will das TapiApp-Objekt. Dieses soll auch die Tapi initialisieren und und die Zugriffe darauf steuern. Das Problem ist, das beim initialisieren der Tapi, dieser eine Callback-Funktion übergeben werden muss, die aber nicht in einer Klasse liegen darf!!! Eine entsprechende nun nackt im Implememntation-Teil erstellte Funktion ist natürlich kein Problem und wird auch aufgerufen. Nur soll die Funktion ja auch alles gemeldete an das TapiApp Objekt weitergeben, aber wie kann ich das (ausser mit einer globalen Variable für das TapiApp Objekt) machen? |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Wie sieht der Callback denn aus? Evtl. kann man da ein wenig tricksen.
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Ich würde das Tapi-Object vermutlich als Singleton implementieren. Der Unterschied zur globalen Variable ist natürlich nicht so wirklich groß, aber es ist doch etwas objektorientierter. Wenn mehrere Instanzen von Klassen informiert werden müssen, dann musst Du noch einen Observer implementieren. Die melden sich an der Singletonklasse an und werden von ihr über die Statusänderungen informiert.
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Delphi-Quellcode:
unit MyTapiObj;
interface type TMyTapiObj = class protected procedure CalledFromCallBack; public constructor Create; destructor Destroy; override; end; implementation var _TapiInitialized : Boolean; _MyTapiObjList : TObjectList; procedure TapiCallBack; var LIdx : Integer; begin for LIdx := 0 to Pred( _MyTapiObjList ) do ( _MyTapiObjList[LIdx] as TMyTapiObj ).CalledFromCallBack; end; procedure TapiInitialize; begin if not _TapiInitialized then begin // Initialization code goes here _TapiInitialized := True; end; end; constructor TMyTapiObj.Create; begin inherited; TapiInitialize; _MyTapiObjList.Add( Self ); end; destructor TMyTapiObj.Destroy; begin _MyTapiObjList.Remove( Self ); inherited; end; initialization _MyTapiObjList := TObjectList.Create( False ); finalization _MyTapiObjList.Free; end. |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Alternativ mal hier in der DP nach MakeProcInstance suchen. Diese Funktion generiert dir einen klassischen Funktionspointer, der aber dafür sorgt, dass dein Callback im Kontext der Objektinstanz ausgeführt wird.
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Wenn es keine Methode sein darf, dann kann man das dennoch als statische Klassenmethode deklarieren, welche die selbe Signaur besitzt, wie eine normale Funktion/Prozedur.
Delphi-Quellcode:
static lässt bei Klassenmethoden das Self weg.
type
TIrgendwas = class class function MyCallback(P: PAnsiChar): Integer; stdcall; static; end; // entspricht function MyCallback(P: PAnsiChar): Integer; stdcall; |
AW: Tapi Callback Funktion darf nicht in Klasse sein
@himitsu
Kann Delphi 6 schon class procedures? |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Hmmmmm, müßte man ausprobieren.
D7 kannte das (glaub ich) zumindestens schon. (wäre ja zu toll, wenn sowas in der OH stünde ... so wie beim MSDN :angle:) |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Eigentlich ist das nicht unbedingt verkehrt, wenn hier Lösungen zu der Frage gepostet werden, die mit der Delphi-Version des Fragenden gar nicht umgesetzt werden können. Wenn jemand nach einem ähnlichen Problem sucht, mag der ja durchaus eine neuere Delphi-Version haben. Man muss sich ja nicht unnötigerweise die Sourcen verrenken.
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Zitat:
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Aus der SDK über die Tapi:
Zitat:
Zitat:
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
IMHO hat nur Zacherl die passende Lösung angeboten ...
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Wie gesagt, eine statische Klassenmethode hat kein Self/this, also kann sie wie eine normale "globale" Funktion verwendet werden.
Eine Methoden und eine normale Klassenmethode haben aber einen "versteckten" noch Self-Parameter, außerdem bestehen diese Methoden-Zeiger aus zwei "Zeigern" (die Codeadresse und das Self), wärend normale Prozeduren und statische Klassenmethoden nur einen Zeiger zur Adressierung benötigen. Im Prinzip ist eine statische Klassenmethode eine "normale" Prozedur (von der Parametern her), nur daß sie "optisch" in einer Klasse drinsteckt. Sie kann auch nicht dynamisch virtuell, abstrakt sein. Es ist halt ein "Design"-Element, um seinen Code aufräumen zu können. |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Du könntest die Klasseninstanz in dwCallbackInstance mitgeben (oder wie der bei den Methodenaufrufen auch heissen mag). Dann bekommst du diese Instanz in der Callback-Methode wieder mit und kannst die passende Instanz aufrufen. Wenn du jetzt noch ein Beispiel für eine Methode zeigst, die du aufrufst, dann könnte man ein Beispiel fertig machen.
Der Hinweis auf die Delphi-Methoden gilt übrigens nicht für statische Klassenmethoden, weswegen die auch als Lösung gehen (siehe Himitsu's Beispiel). Damit kann man dann die ganze API in eine Klasse wrappen, braucht keine globalen Prozeduren und keine globale Singleton-Instanz. |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Zitat:
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Mein Delphi 6 kennt zwar scheinbar "class function" aber nicht "static". Womit Himis Ansatz für mich wohl nicht funktioniert.
Zacherls Ansatz werd ich mal suchen, doch die ersten 2-3 Post dazu haben mich schon verwirrt, aber mal sehen. Sir Rufos Ansatz sieht aber auch machbar aus, nutzt dann aber auch einen globalen Ansatz (wenn auch nicht eine globale Variable vom TapiApp-Object exisiert, was schonmal eine Verbesserung gegenüber meiner Notlösung ist). |
AW: Tapi Callback Funktion darf nicht in Klasse sein
@Jumpy
Zeig doch mal wie der CallBack initialisiert wird. Es scheint, du musst da die Instanz mitgeben, denn dann brauchst du keine Liste über die Instanzen mitführen. Irgendwoher muss ja die dwCallbackInstance herkommen und die kannst du in der globalen proc auswerten, damit du weißt wohin der Aufruf gehen soll. Hab gerade mal gegooglet und dwCallbackInstance ist wohl der Handle zur App, also wohl doch selber verwalten, wenn die Nachricht an mehrere interne Instanzen soll. |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Liste der Anhänge anzeigen (Anzahl: 1)
@DeddyH/Uwe: Ich verstehe leider nicht genau, worauf ihr bei eurer Frage hinauswollt und welche Infos ihr noch braucht. Ich häng mal die Highlights der Unit wie sie bisher war, mit globaler Variable usw. hier an:
Die externe Callback-Prozedur benutzt die globale Variable MyTapi um, wenn aufgerufen, auf das MyTapi-Objekt zuzugreifen und z.B. in diesem Objekt registrierte andere Callback-Routinen zu feuern usw.Eine andere solche Callback-Routine steht in der Main-Unit, die das MyTapi-Objekt erstellt und das die Nachrichten, die über die eigene Callback kommen für die Geschäftslkogik benutzt. Edit: Als Dateianhang die Unit Tapi, eine Tapi-Kapselung von den Jedis?
Delphi-Quellcode:
Auszug aus Main-Unit
unit uMyTapiObj;
interface uses tapi, Dialogs, SysUtils, ShellAPI, windows, Forms; const {$IFDEF Win32} TapiDll = 'tapi32.dll'; {$ELSE} TapiDll = 'tapi.dll'; {$ENDIF} TAPI_HiVer = $00030000; // Highest API version wanted (3.0) TAPI_LoVer = $00010004; // Lowest API version accepted (1.4) TAPI_NegHi = $00030000; // High API Version for negotiation purposes TAPI_NegLo = $00010000; // Low API Version for negotiation purposes maxBufSize = $3FF; // Größe des Datenbuffers für Datenrückgabe // (Stichwort: Variabler Teil für Strings) LINE_PROGRAMCHECK = 127; // Virtuelle TAPI_Message für Timer-gesteuerte Checks type TLineCallbacks = array of TLineCallBack; // Nimmt die Adressen der gesetzten Callbackroutinen auf //**************************************************************************** // TMyTapi: Klasse für die Tapi selbst // die Instanz MyTapi muss created und initialized werden, da diese // den callback mechanismus implementiert. // Beim Aufruf von initialize muss ein Pointer auf die Callback Routine // im aufrufenden Modul übergeben werden. //**************************************************************************** TMyTapi = class(TObject) private priv_Initialized: boolean; priv_LineApp: HLINEAPP; priv_hInstance: Cardinal; priv_IDStr: PChar; priv_NumDevs: Cardinal; priv_Version: Cardinal; priv_LineInitializeExParams: LineInitializeExParams_tag; priv_LineCallback: TLineCallbacks; priv_CallbackCount: integer; function AddCall(Line: integer; CallHandle: hCall): boolean; function RemoveCall(CallHandle: hCall): boolean; public constructor Create; destructor Destroy; override; procedure AddCallback(CallbackProcedure: TLineCallback); // Hinzufügen einer Callback Routine procedure RemoveCallBack(CallbackProcedure: TLineCallback); // Entfernen einer Callback Routine property CallbackCount: integer read priv_CallbackCount; // Anzahl der hinzugefügten Callback Routinen property ID_Str: PChar read priv_IDStr; function Initialize: boolean; property Initialized: boolean read priv_Initialized; property LineApp: HLINEAPP read priv_LineApp; property NumDevs: cardinal read priv_NumDevs; property TAPI_Version: string read get_Version; end; //****************************************************************************** // MyTapi muß erzeugt und initialisiert werden !!! // wird von allen Objekten benutzt um auf Tapi Funktionen zuzugreifen //****************************************************************************** var MyTapi: TMyTapi; implementation //****************************************************************************** // Master Callback Routine // - Kümmert sich um neue Calls und löscht diese bei LINECALLSTATE_IDLE // - ruft alle registrierten callback Routinen auf //****************************************************************************** procedure priv_MyCallback(hDevice, dwMsg, dwCallbackInstance, dwParam1, dwParam2, dwParam3: Cardinal); stdcall; var i: integer; begin try case dwMsg of LINE_PROGRAMCHECK: begin end; LINE_APPNEWCALL: begin if MyTapi.priv_SupportCalls then MyTapi.AddCall(dwCallbackInstance, dwParam2); end; LINE_CALLSTATE: begin if MyTapi.priv_SupportCalls then begin i := low(MyTapi.priv_calls); while (MyTapi.priv_calls[i].priv_CallHandle <> hDevice) and (i < high(MyTapi.priv_calls)) do inc(i); if MyTapi.priv_calls[i].priv_CallHandle = hDevice then begin if (dwParam1 = LINECALLSTATE_IDLE) then MyTapi.RemoveCall(hDevice) else MyTapi.priv_Calls[i].initialize(hDevice); end else begin MyTapi.AddCall(dwCallbackInstance, hDevice); end; end; end; LINE_CALLINFO: begin if MyTapi.priv_SupportCalls then begin i := low(MyTapi.priv_calls); while (MyTapi.priv_calls[i].priv_CallHandle <> hDevice) and (i < high(MyTapi.priv_calls)) do inc(i); if MyTapi.priv_calls[i].priv_CallHandle = hDevice then begin MyTapi.priv_Calls[i].initialize(hDevice); end; end; end; LINE_CLOSE, LINE_CREATE, LINE_REMOVE: begin (*if (*)shellexecute(Application.Handle, 'open', PChar(ParamStr(0)), nil, PChar(ExtractFilePath(ParamStr(0))), SW_SHOWNORMAL)(* <= 32) then ShowMessage('Bitte Telefonliste neu starten!')*); Application.MainForm.Close; Application.Terminate; end; else begin // MyTapi.ShowWarning('Code: ' + IntToStr(dwMsg) + // ', Line: ' + IntToStr(dwCallbackInstance), 'priv_MyCallback'); end; end; if MyTapi <> nil then if MyTapi.Initialized then begin for i := 0 to MyTapi.CallbackCount - 1 do begin MyTapi.priv_LineCallback[i](hDevice, dwMsg, dwCallbackInstance, dwParam1, dwParam2, dwParam3); end; if MyTapi.priv_debugging then try MyTapi.priv_LogDebug(Tapi_Messages[dwMsg], IntToStr(dwCallbackInstance)); except end; end; except MyTapi.ShowWarning('Error: priv_MyCallback', 'uMyTapiObj'); end; end; { TTapiSP } constructor TMyTapi.Create; begin inherited Create; priv_Initialized := false; priv_IDStr := 'Test'; priv_hInstance := hInstance; nd; destructor TMyTapi.Destroy; begin LogErrors := false; priv_LineCallback := nil; inherited Destroy; MyTapi := nil; end; function TMyTapi.get_Version: string; begin Result := IntToStr(priv_Version div $10000) + '.' + IntToStr(priv_Version mod $10000); end; function TMyTapi.Initialize: boolean; var i: integer; begin Result := false; try // initialisieren der MyLineInitializeExParams FillChar(priv_LineInitializeExParams, SizeOf(priv_LineInitializeExParams), 0); with priv_LineInitializeExParams do begin dwTotalSize := sizeof(priv_LineInitializeExParams); // welcher Signalisierungstyp wird benutzt: // LINEINITIALIZEEXOPTION_USEHIDDENWINDOW // LINEINITIALIZEEXOPTION_USEEVENT // LINEINITIALIZEEXOPTION_USECOMPLETIONPORT dwOptions := LINEINITIALIZEEXOPTION_USEHIDDENWINDOW; end; priv_Version := TAPI_NegHi; try // Verbindungsaufnahme mit der TAPI // - TAPI Version aushandeln, die maximal benutzt werden kann // Callback Routine registrieren // Anzahl der Lines priv_Initialized := (lineInitializeEX(@priv_LineApp, priv_hInstance, priv_MyCallback, priv_IDStr, priv_NumDevs, priv_Version, priv_LineInitializeExParams) >= 0); except priv_Initialized := false; end; if priv_Initialized then begin SetLength(priv_Lines, priv_NumDevs); for i := Low(priv_lines) to High(priv_lines) do begin priv_Lines[i] := TMyInnoLine.Create; priv_Lines[i].Initialize(i); if priv_Lines[i].isInno and priv_SupportCalls then priv_Lines[i].LookForNewCalls; end; end; Result := priv_Initialized; except ShowWarning('Error: TMyTapi.Initialize', 'uMyTapiObj'); end; end; //****************************************************************************** // Einen neuen Call in die Liste aufnehmen //****************************************************************************** function TMyTapi.AddCall(Line: Integer; CallHandle: hCall): boolean; var i: integer; newLength: integer; begin try if priv_SupportCalls then begin inc(priv_CallCount); SetLength(priv_Calls, priv_CallCount); i := high(priv_calls); priv_Calls[i] := TMyCall.Create; Result := priv_Calls[i].initialize(CallHandle); if Result then begin newLength := High(priv_Lines[Line].priv_MyCalls) + 2; SetLength(priv_Lines[Line].priv_MyCalls, newLength); priv_Lines[Line].priv_MyCalls[newLength - 1] := priv_Calls[i]; end; end else begin Result := false; ShowWarning('Support of Calls disabled', 'MyTapi.AddCall'); end; except Result := false; ShowWarning('Error: TMyTapi.AddCall', 'uMyTapiObj'); end; end; //****************************************************************************** // Einen bestehenden Call aus der Liste löschen //****************************************************************************** function TMyTapi.RemoveCall(CallHandle: hCall): boolean; var i, j: integer; i2, j2, k2: integer; begin try if priv_SupportCalls then begin i := low(priv_calls); while (priv_calls[i].priv_CallHandle <> CallHandle) and (i < high(priv_calls)) do inc(i); if priv_calls[i].priv_CallHandle = CallHandle then begin for i2 := Low(priv_Lines) to High(priv_Lines) do begin for j2 := Low(priv_Lines[i2].priv_MyCalls) to High(priv_Lines[i2].priv_MyCalls) do begin if priv_Lines[i2].priv_MyCalls[j2].priv_CallHandle = CallHandle then begin for k2 := j2 to High(priv_Lines[i2].priv_MyCalls) - 1 do begin priv_Lines[i2].priv_MyCalls[k2] := priv_Lines[i2].priv_MyCalls[k2 + 1]; end; SetLength(priv_Lines[i2].priv_MyCalls, High(priv_Lines[i2].priv_MyCalls)); end; end; end; priv_calls[i].Destroy; for j := i to high(priv_Calls) - 1 do priv_Calls[j] := priv_Calls[j + 1]; dec(priv_CallCount); Setlength(priv_Calls, priv_Callcount); Result := true; end else begin Result := false; end; if Result then begin end; end else begin Result := false; ShowWarning('Support of Calls disabled', 'MyTapi.RemoveCall'); end; except Result := false; ShowWarning('Error: TMyTapi.RemoveCall', 'uMyTapiObj'); end; end; //****************************************************************************** // Eine Callback Routine registrieren //****************************************************************************** procedure TMyTapi.AddCallback(CallbackProcedure: TLineCallback); begin try inc(priv_CallbackCount); SetLength(priv_LineCallback, priv_CallbackCount); priv_LineCallback[High(priv_LineCallback)] := CallbackProcedure; except ShowWarning('Error: TMyTapi.AddCallback', 'uMyTapiObj'); end; end; //****************************************************************************** // Registrierung einer Callback Routine entfernen //****************************************************************************** procedure TMyTapi.RemoveCallBack(CallbackProcedure: TLineCallback); var i, j: integer; begin try i := Low(priv_LineCallback); while (@priv_LineCallback[i] <> @CallbackProcedure) and (i < High(priv_LineCallback)) do inc(i); if @priv_LineCallback[i] = @CallbackProcedure then begin for j := i to High(priv_LineCallback) - 1 do priv_LineCallback[j] := priv_LineCallback[j + 1]; dec(priv_CallbackCount); SetLength(priv_LineCallback, priv_CallbackCount); end else begin ShowWarning('Warning: can''t remove Callback!', 'uMyTapiObj'); end; except ShowWarning('Error: TMyTapi.RemoveCallback', 'uMyTapiObj'); end; end; function TMyTapi.getMemStr(Buffer: TBuffer; Offset, Size: Cardinal): string; var s: string; c: char; i: integer; begin s := ''; try try for i := Offset to Offset + Size - 1 do begin c := Buffer[i]; if c in [#0..#31] then c := ' '; s := s + c; end; except ShowWarning('Error: TMyTapi.getMemStr', 'uMyTapiObj'); raise; end; finally Result := s; end; end; end.
Delphi-Quellcode:
Also auch sieht das irgendwie unschön aus.
unit aMain;
interface uses Projekt, uMyTapiObj, Tapi,... type TMain = class(TForm) ActionList1: TActionList; MainMenu1: TMainMenu; StatusBar: TStatusBar; //usw end; procedure MyCallback(hDevice, dwMsg, dwCallbackInstance, dwParam1, dwParam2, dwParam3: Cardinal); stdcall; var Main: TMain; implementation procedure MyCallback(hDevice, dwMsg, dwCallbackInstance, dwParam1, dwParam2, dwParam3: Cardinal); stdcall; begin case dwMsg of LINE_CALLSTATE: begin case dwParam1 of LINECALLSTATE_IDLE: begin Main.ChangeLineState(dwCallbackInstance, ReplaceMessage); end; LINECALLSTATE_OFFERING: begin Main.ChangeLineState(dwCallbackInstance, ReplaceMessage, 'neuer Anruf', ShowNumbers); end; LINECALLSTATE_ACCEPTED: begin Main.ChangeLineState(dwCallbackInstance, ReplaceMessage, 'klingelt', ShowNumbers); end; LINECALLSTATE_DIALTONE: begin Main.ChangeLineState(dwCallbackInstance, ReplaceMessage, 'Wählton'); //hier end; LINECALLSTATE_DIALING, LINECALLSTATE_PROCEEDING: begin Main.ChangeLineState(dwCallbackInstance, ReplaceMessage, 'wählt'); //hier end; LINECALLSTATE_RINGBACK: begin Main.ChangeLineState(dwCallbackInstance, ReplaceMessage, 'Ziel erreicht', ShowNumbers); end; //usw. end; procedure TMain.FormCreate(Sender: TObject); var i:Integer; begin //... MyTapi := TMyTapi.Create; if MyTapi.Initialize then begin MyTapi.AddCallback(amain.MyCallback); end else // //... end; |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Das ist mir etwas zu viel Code zum schnellen Suchen, aber wird dwCallbackInstance nirgends gesetzt? Wenn die nirgends übergeben werden kann, ist ja der Parameter sinnlos.
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Hab mich etwas selber verwirrt und daher eure Fragen nicht verstanden:
dwCallbackInstance kann u.a. mit irgend so einer anderen Tapi-Funktion gesetzt werden, aber die Tapi-Schnittstelle(?) unserer Telefonanlage unterstützt das nicht, d.h. da kommt immer 0 zurück. Scheinbar ist das von Anlage zu Anlage untersch. welche Tapi-Funktionalitäten genau unterstützt werden. D.h. da ist nix zu holen. Mein Ziel ist es halt, das die sich nicht innerhalb einer Klasse befindliche CallBack-Prozedur, die ich der tapi bei der intitialisierung übergebe(n muss), die gefeuerten Events / Nachrichten, an meine Klasse weitergibt. Notfalls wohl dann wie bei Sir Rufo, wo die Callback auf eine global deklarierte Liste zugreifen kann in der sich (im meinem Fall nur die) eine Klasse registrieren kann, an die die Callbacks weitergeleitet werden sollen. Der Ist-Zusatand den wir momentan haben gefällt mir halt nicht, z.B. welche Objekte wir da haben und wie die zueinander stehen. AUch fehlen mit Funktinalitäten, bisher wird die Anlage nur überwacht. Jetzt soll sie damit auch gesteuert werden können (z.B. Rufe umleiten usw.) Dazu bau ich das halt aus und um und wollt das irgendwie "sauber" hinkriegen, ohne die globale Variable MyTapi. Bei Forms mach ich das auch so, ausser der Main-Form lösch ich immer alle diese Variablen ala Form2:TForm2 usw. aus den Units und leg mir entsprechedne Variablen da an wo ich das Form aufrufen will, und das wollt ich halt hier auch machen. |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Zitat:
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Allerdings hätte ich auch einiges an Verbesserungen zum Code:
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Das oben gezeigte ist auszugsweise der Ist-Zustand, von dem ich ja weg will. Daher sind Verbesserungsvorschläge gerne gesehen. Mein irgendwann fertiges TapiApp-Object soll wie z.Zt. MyTapi eine Liste von Callback-Funktionen verwalten. Diese können dann tatsächlich so aussehen wie ich das will, sprich welche Parameter usw. Zu deinem
Delphi-Quellcode:
könnte dann vllt. noch ein:
type
TTapiCallbackMethod = procedure ( hDevice, dwMsg, {dwCallbackInstance, } dwParam1, dwParam2, dwParam3 : Cardinal ) of object;
Delphi-Quellcode:
kommen. Geht das? Oder sind so Methodenzeiger (das ist das doch) besser in einer T(Object)List o.ä. aufgehoben?
TTapiCallbackMethods = Array of TTapiCallbackMethod
------- Es gibt wenn man so will 2 Arten von Callback Funktionen. Eine "Master"-CallBack-Funktion für die Tapi ausserhalb von Objekten, die aber auch an mein Objekt alles weitergeben soll und dann andere Callback-Funktionen (diesmla gerne auch von anderen Objekten), die in meinem Objekt gelistet sind und an die so auch die ursprüngliche Tapi-Message (ggf. in angepasster Form) weitergegeben wird. ------- Wenn ich nun MyTapi als Singelton (muss ich mir nochmal genauer anschauen) umsetzte, kann ich das denn auch in meiner aussserhalb von Objekten (nur im Application-Kontext) deklarierten CallFunktion benutzen? |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Zitat:
Zitat:
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Das Weiterleiten einer Callback-Funktion auf die Callback-Methode ist doch ganz einfach!
Delphi-Quellcode:
procedure priv_MyCallback(hDevice,
dwMsg, dwCallbackInstance, dwParam1, dwParam2, dwParam3: Cardinal); stdcall; begin if dwCallbackInstance = 0 then begin // Oh ohhh, das sollte nie vorkommen (wäre ganz klar ein Fehler des Programmierers) Assert(False); end else begin try TMyTapi(dwCallbackInstance).MyCallback(hDevice, dwMsg, dwParam1, dwParam2, dwParam3); except // Exception loggen oder anzeigen // auf jeden Fall sollte keine Exception dem Aufrufer um die Ohren fliegen end; end; end; |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Das ist doch ziemlich genau das, was ich weiter vorn bereits gesagt habe. Mir ist nur noch nicht klar, wie man dwCallbackInstance belegen kann.
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Zitat:
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Zitat:
Zitat:
Delphi-Quellcode:
Sehe leider nicht, wie ich das gebrauchen kann, um auf mein Objekt zu zeiegn. Werde also versuchen mein TapiApp-Object als Singelton zu implementieren.
var priv_hInstance:Cardinal;
priv_hInstance := hInstance; //hInstance aus Sysinit lineInitializeEX(@priv_LineApp,priv_hInstance,priv_MyCallback,//... |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Zitat:
|
AW: Tapi Callback Funktion darf nicht in Klasse sein
Kommando zurück. Hab komplett an der falschen Stelle gesucht. Der Parameter wird bei lineOpen übergeben, das man für jede Telefonleitung, die man überwachen will, aufruft.
Zitat:
Also ist es ja vllt. doch möglich da einen Verweis auf mein Objekt hinzukriegen. Hoffe es hilft mir noch jemand nach der ganzen Verwirrung. Wenn ich innerhalb meines Objectes für jede Line lineOpen aufrufe, wie kann ich dann dabei einen Pointer(?) auf mein Objekt in dwCallbackInstance mitgeben, das ja vom Typ DWORD ist? Und wie muss ich dieses DWORD in der Callback-Funktion auswerten, um da wieder auf mein Objekt zu kommen? So wie shmia das andeutet, indem ich das in mein Objekt caste? TMyTapi(dwCallbackInstance). |
AW: Tapi Callback Funktion darf nicht in Klasse sein
Unter Win32 (genauer: in 32Bit-Anwendungen) kannst Du Instanzen problemlos nach DWORD casten und zurück. Also kannst Du bei der Initialisierung dann DWORD(self) übergeben und im Callback dann mit TDeineKlasse(dwCallbackInstance) auf die Instanz zugreifen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz