Autor |
Beitrag |
Peter18
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Di 16.06.15 11:52
Ein freundliches Hallo an alle,
immer Ärger mit den Pointern. Ich dachte die Tapi ist abgehakt, aber ein typischer Fall von denkste!
In diesem Fall soll ein Anrufmonitor den Anrufer zeigen. Aber mein Compiler scheint die Schnittstelle der Callback-Routine nicht korrekt zu erstellen. Ein bis zwei Anrufe werden signalisiert, dann ist Feierabend. Da auch ein Anrufmonitor aus den Internet nichts mehr sagt, gehe ich davon aus, das die TAPI zersägt worden ist. Nach Neustart geht es dann manchmal wieder, doch irgend wann ist auch das vorbei und es hilft nur die TAPI neu zu installieren.
Das steht in der Tapi.pas:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| TTAPICallback = procedure(hDevice, dwMessage: DWORD; dwInstance, dwParam1, dwParam2, dwParam3: DWORD_PTR) stdcall; TLineCallback = TTAPICallback; LINECALLBACK = TLineCallback; {$EXTERNALSYM LINECALLBACK} |
Das steht in meiner Unit:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| .... Type Ba = Array [0..500] of Byte; PBa = ^Ba;
procedure LineCallBack( hDev, Msg, Cbi, P1, P2, P3 : DWord ); stdcall; .... |
Das Array dient zum kopieren der Rufnummern. Wenn ich die Type-Deklaration von dort unter "implementation" verschiebe, ändert sich die Fehlermeldung. Setze ich sie erneut an diese Stelle ändert sie sich jedoch nicht!
In dieser Zeile wird die "LineCallBack" angemeckert und das mit den unterschiedlichsten Fehlermeldungen.
Delphi-Quelltext 1:
| R := lineInitialize( @Luh, HInstance, LineCallBack, PChar( 'Test' ), DC ); |
Mal behauptet er die "LineCallBack" wäre nicht global deklariert, mal erwartet er ein "(" und findet ",". Mal geht es nur mit "@LineCallBack," und mal mit "LineCallBack,". Das Merkwürdige ist, mache ich die Änderung rückgängig (Auskommentieren) erscheint nicht immer der selbe Fehler wie zuvor.
Bei " procedure T_Tapi.WriteCallMon( B : Boolean );" wird nicht gemeckert, aber bei " procedure Dial( Nr: String; V : DWord; GeraetInd : DWord; Modem : Boolean );".
Bei dem Ganzen habe ich etwas die Peilung verloren, vielleicht kann mich jemand wieder auf Kurs bringen. Ist es vielleicht sinnvoll die CallBack in eine extra Unit zu stecken? Oder die CallBack einer Pointervariablen zuweisen? Oder kann ich die Deklaration in der Tapi.pas nutzen?
Ich hoffe auf einen guten Tipp und grüße von der sonnigen Nordsee
Peter
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Mi 17.06.15 13:22
Deine LineCallback Funktion sollte so aussehen (analog zur TTAPICallback)
Delphi-Quelltext 1:
| procedure myLineCallback(hDevice, dwMessage: DWORD; dwInstance, dwParam1, dwParam2, dwParam3: DWORD_PTR) stdcall; |
und beim Aufruf solltest du @LineCallback uebergeben. Das geht auch nur wenn die Funktion keine Methode ist.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| unit bla;
interface
uses windows, usw;
procedure myLineCallback(hDevice, dwMessage: DWORD; dwInstance, dwParam1, dwParam2, dwParam3: DWORD_PTR) stdcall;
implementation
procedure myLineCallback(hDevice, dwMessage: DWORD; dwInstance, dwParam1, dwParam2, dwParam3: DWORD_PTR) stdcall; begin end;
|
Ausserdem solltest dir auch mal lineInitializeEx anschauen
Achtung: eventl ist auch deine TTAPICallback falsch (DWORD_PTR wird in PDWORD sein) das ist dann nicht korrekt
ggf. hilft dir das:
gedemin.googlecode.c...trunk/Comp5/tapi.pas
Edit:
deine TTAPICallback ist falsch deklariert, msdn.microsoft.com/e...12%28v=vs.85%29.aspx
also stimmt mein Code oben nicht, du musst aber trotzdem @myLineCallback verwenden (und die Funktion sollte anders heissen als LINECALLBACK wenn du das schon deklariert hast)
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
Für diesen Beitrag haben gedankt: Peter18
|
|
Peter18
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Mi 17.06.15 17:16
Hallo Daniel,
endlich kann ich mich auch mit dieser Antwort befassen. Dank Dir auch dafür!
Da bei MS
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| VOID FAR PASCAL lineCallbackFunc( DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3 ); | steht habe ich alles als "DWORD" deklariert. Die Ergebnisse waren ok. Aber vielleicht macht "PASCAL" den Untreschied. In meinem C++ Buch steht davon nichts, aber vielleicht hätte ich das Internet bemühen sollen.
Auf jeden Fall konnte ich das Ganze Übersetzen. Werd mal Testen und Berichten.
Grüße von der Nordsee wo es nach Regen aussieht
Peter
|
|
Peter18
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Do 18.06.15 11:19
Hallo Daniel,
die "CallBack" heißt bei mir jetzt "Line_CallBack" und hat Parameter wie in der "Tapi.pas". Es wird mir auch ein Anruf gemeldet. Manchmal ein Zweiter. Dann ist Sendepause. Erst wenn ich das Programm neu starte wird die CallBack wieder aufgerufen. Zur Kontrolle hatte ich mir einen tapibasierten Anrufmonitor aus dem Internet geholt. Der verhält sich genau so, wenn mein Programm läuft. Läuft er allein, wird aber jeder Anruf gemeldet. Offenbar zersägt irgendetwas die TAPI. Kann es sein, dass der Kompiler ein Problem mit der CallBack hat??
Grüße von der wolkigen Nordsee
Peter
|
|
SMO
Beiträge: 120
Erhaltene Danke: 18
D2005 Personal
|
Verfasst: Do 18.06.15 15:36
"PASCAL" ist die Aufrufkonvention, entspricht "stdcall".
Nein, der Kompiler hat kein Problem mit Callbacks. Wenn es nicht richtig funktioniert, muss noch irgendwo ein Fehler sein.
|
|
jaenicke
Beiträge: 19285
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 18.06.15 16:40
SMO hat folgendes geschrieben : | "PASCAL" ist die Aufrufkonvention, entspricht "stdcall". |
Nein, bei Pascal werden die Parameter von links nach rechts auf dem Stack abgelegt, bei stdcall von rechts nach links!
Es ist also hier wichtig das passende zu benutzen, sonst kommen die Parameter verkehrt herum an, sprich die falschen Werte werden an die Parameter übergeben.
Für diesen Beitrag haben gedankt: SMO
|
|
Peter18
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Do 18.06.15 16:55
Hallo SMO,
Dank Dir für die Antwort. Irgend wo anders ein Fehler? Preisfrage: Aber wo??
Vielleicht stimmt der Ablauf ja nicht und es fehlt irgend ein Schritt. Ich hoffe jemand kann mir dazu einen Tipp geben. In "Windows Telephony Programming" habe ich nichts dazu gefunden.
Quelltext 1: 2: 3: 4: 5: 6:
| Der Ablauf ist folgender: lineInitialize, lineOpen für alle "voice-Geräte" In der "Line_CallBack": eingehender Anruf: lineGetCallInfo ==> Rufnummern LINECALLSTATE_IDLE: lineDeallocateCall |
Muß ich vielleicht ein CloseLine und dann wieder lineOpen machen???
Grüße von der Nordsee
Peter
Zuletzt bearbeitet von Peter18 am Do 18.06.15 17:07, insgesamt 1-mal bearbeitet
|
|
Peter18
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Do 18.06.15 17:03
Hallo Sebastian,
Dank Dir für die Klärung. Paßt das Ganze denn dann überhaupt zusammen? Die Reihenfolge scheint ja zu stimmen, denn bei "R := lineDeallocateCall( hDevice );" ist R = 0, also kein Fehler.
grüße von der Nordsee
Peter
|
|
SMO
Beiträge: 120
Erhaltene Danke: 18
D2005 Personal
|
Verfasst: Do 18.06.15 17:13
jaenicke hat folgendes geschrieben : | Nein, bei Pascal werden die Parameter von links nach rechts auf dem Stack abgelegt, bei stdcall von rechts nach links! |
Stimmt, hatte ich ganz vergessen! Allerdings behandelt Win32 "PASCAL" als Synonym für "WINAPI", was beides "__stdcall" in C entspricht ( siehe, und hier).
Die Frage ist also, stimmt die TTAPICallback Deklaration mit "stdcall" oder müsste es tatsächlich "pascal" sein? Ich habe TAPI noch nie benutzt, aber ich vermute stdcall wird schon korrekt sein.
|
|
jaenicke
Beiträge: 19285
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 18.06.15 17:31
In der API Beschreibung wird stdcall gemeint sein. Das fiese ist, dass pascal eigentlich die Bezeichnung für die Übergabe auf dem Stack ist. Stdcall ist eine Unterform, die die Parameter umgekehrt übergibt.
Pascal und stdcall gibt es in Delphi in dieser Form. In C gibt es aber nur cdecl und stdcall, so dass dort mit Pascal die Übergabe auf dem Stack gemeint ist, aber eben in Form der Unterform stdcall.
Stdcall wird also stimmen.
|
|
Peter18
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Fr 19.06.15 12:00
Ein freundliches Hallo an alle,
nachdem die Unsicherheit bei der CallBack einigermaßen beseitigt war, habe ich die Meldungen geprüft, die noch nicht bearbeitet wurden. Es zeigte sich, dass nach dem Trennen der Verbindung "LINECALLSTATE_ONHOLD" und dann "LINECALLSTATE_IDLE" mitgeteilt wird. Anscheinend ist "LINECALLSTATE_ONHOLD" die Ursache. Danach wird die Leitung anscheinend offen gehalten, um weitere Aktionen wie Dial durchzuführen. Lt. MS sollte dieser Status nicht auftauchen: Zitat: | The new call state. This parameter must be one and only one of the following LINECALLSTATE_ constants. |
( msdn.microsoft.com/e...20%28v=vs.85%29.aspx ). Nachdem ich nun die Leitung schließe und erneut öffne funktioniert es wie gewünscht.
Grüße von der regenrischen Nordsee
Peter
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Fr 19.06.15 14:24
Wenn
msdn.microsoft.com/e...12%28v=vs.85%29.aspx
und
de.wikipedia.org/wiki/Aufrufkonvention
stimmt dann ist das eine umgedrehte stdcall (?):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure lineCallbackFunc( DWORD dwParam3, DWORD dwParam2, DWORD dwParam1, DWORD dwCallbackInstance, DWORD dwMsg, DWORD hDevice ); cdecl; |
In einem anderen MS Artikel wurde auf die Funktion
msdn.microsoft.com/e...57%28v=vs.85%29.aspx
verwiesen.
Edit: auf wiki steht dort "cdecl + Parameter links->rechts + Funktion selber aufraemen" das sollte dann einem "stdcall + Parameter links->rechts" entsprechen, ist dort echt mies beschrieben
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
SMO
Beiträge: 120
Erhaltene Danke: 18
D2005 Personal
|
Verfasst: Fr 19.06.15 14:58
uall@ogc hat folgendes geschrieben : | dann ist das eine umgedrehte stdcall (?) |
Das haben jaenicke und ich doch bereits geklärt. Ja, die Aufrufkonvention "pascal" (Delphi) bzw. "__pascal" (C) ist ein "umgedrehtes stdcall".
Windows 3.x (16 bit) hat das wohl auch tatsächlich benutzt. In der 32 bit Windows API findet man noch immer gelegentlich "PASCAL" Definitionen, wohl aus historischen Gründen, aber dieses "PASCAL" ist eben nicht "__pascal". In der WinAPI Headerdatei WinDef.h wird nämlich "PASCAL" als "__stdcall" definiert (gleiches gilt für WINAPI und CALLBACK).
Es stimmt also alles, die TAPI "lineCallbackFunc" ist stdcall.
|
|
|