Autor Beitrag
Peter18
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mo 01.12.14 17:15 
Ein freundliches Hallo an alle!

Diese Frage habe ich zwar im Api-Forum schon gestellt, aber vielleicht passt sie hier besser hin:

Ich möchte von der TAPI alle installierten Geräte gelistet bekommen. Dazu gibt es eine Basisstruktur, die in der TAPI definiert ist. Da aber variable Datenmengen zurüchgegeben werden, und der nötige Speicher dort nicht angehängt werden kann, muß die Struktur von mir erweitert werden, wenn die Fehlermeldung "LINEERR_STRUCTURETOOSMALL 0x8000004D" zurückgegeben wird. Da Pascal die Speicherverwaltung anders handhabt bin ich mir nicht sicher, ob ich das C-Beispiel direkt umsetzen kann oder ob ich anders vorgehen muß.

In C Wird die Struktur mit realloc erweitert, damit an den Kopf die Infornationen angehängt werden kann. Doch wie muß ich das in Delphi 4 handhaben??
"LDC : TLineDevCaps;" deklariert den Kopf der Struktur. Übergeben wird der Pointer "lpLineDevCaps: PLineDevCaps".

Wie kann ich den Speicher Pascal-conform erweitern? Muß ich am Ende der Funktion den Speicher wieder freigeben oder geschieht das automatisch wenn die Variable ungültig wird??

Grüße von der Nordsee

Peter
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Mo 01.12.14 17:27 
Die Antwort findest du in der PN, deswegen hatte ich dir das alles geschickt. In Delphi nimmst du ReallocMem und zum Freigeben dann FreeMem.
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1321
Erhaltene Danke: 117

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Mo 01.12.14 17:31 
Lege doch einfach von vorne herein einen Puffer an der groß genug ist. Wiviele Geräte können es denn maximal sein die Du erwarten kannst? Einfach mal zwei und fürs erste ist es gut.
Wenn dann der Fehler doch mal kommen sollte, dann einfach den Puffer um die zu erwartende Menge vergrößern und wieder alles abrufen.
Ich weiß, ist ein bisschen Speicherverschwendung, aber immernoch besser als x-mal die Meldung bekommen und immer wieder den Speicher vergrößern.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Di 02.12.14 14:11 
Hallo baumina, hallo Sinspin,

Dank euch beiden. Inzwischen habe ich die entspechende Stelle in bauminas Beispiel gefunden und es funktioniert! Was ich aber nicht ganz verstehe ist das Funktionsergebnis von "lineGetDevCaps". Statt Fehlercode ist es jetzt immer 0.

Grüße von der trüben Nordsee

Peter
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Di 02.12.14 14:51 
Nun - wenn du dich auf Quellcode beziehst, denn dir jemand per PN geschickt hat, solltest du wohl auch per PN antworten. Die Glaskugel ist grade in der Reperatur.
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Di 02.12.14 17:59 
Hallo Boldar,

schade dass Deine Glaskugel nicht funktioniert, ich hoffe sie ist nicht ganz kaputt. Sorry hatte jede Menge Testzeilen und viel auskommentiert. Es ist immer noch überflüssiges von verschiedenen Tests darin! Hier nun für alls die Testroutine, die die Geräte auflistet:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
procedure TForm1.Button1Click(Sender: TObject);
const
  LINEINITIALIZEEXOPTION_USECOMPLETIONPORT = 0;
var
  Tel : ITTAPI;
  C   : RequestMakeCall;
  D   : ITDispatchMapper;
  l   : OleVariant;
  I   : Integer;
  A   : IEnumAddress;
  CI  : ITCallInfo;
  Ad  : ITAddress;
  Al  : IEnumAddress;
  Cc  : ITBasicCallControl;
  Par : lineinitializeexparams_tag;
//  LD  :
  R   : LongInt;       
  Luh       : HLineApp;    
  LDC       : PLineDevCaps;
  DC, Tv    : Cardinal;
  Lo, Hi, V : DWord;
  NSize, Ln : DWord;
  LeId      : TLineExtensionID;
  CCo, AC   : PChar;
  H         : HWND;

  aName     : array[0..500of AnsiChar;

begin
  Lo  := $00010003;   // Tapi 1.3
  Hi  := $00030000;   // Tapi 3.0
  R   := -2;
  H   := unassigned;


  FillChar(Par, SizeOf(Par), 0);
  R  := lineInitialize( @Luh, HInstance, @LineCallBack, PChar( 'Test' ), DC );  //    LineCallBack  @Par
//  ShowMessage( 'Result:  ' + Inttostr( R ) + Char( $0D ) + 'Hex:  ' + IntToHex( R, 8 ) );
  if R = 0 then
  begin
    for I := 0 to DC-1 do
    begin
      R := lineNegotiateAPIVersion( Luh, I, Lo, Hi, V, LeId );
//      ShowMessage( 'Result:  ' + Inttostr( R ) + Char( $0D ) + 'Hex:  ' + IntToHex( R, 8 ) );
      if R = 0 then
      begin
        if I < 10 then foTapiV[ I ] := V;

        LDC              := AllocMem( SizeOf(TLineDevCaps) );     
        LDC^.dwTotalSize := SizeOf( TLineDevCaps );

        R     := lineGetDevCaps( Luh, I, V, 0, LDC );
        if LDC^.dwTotalSize < LDC^.dwNeededSize then
        begin
          NSize := LDC^.dwNeededSize;
          FreeMem( LDC );    
          LDC              := AllocMem( NSize );     
          LDC^.dwTotalSize := NSize;
          R := lineGetDevCaps( Luh, I, V, 0, LDC );
        end;
        if LDC^.dwLineNameSize > 0 then
        begin
          if LDC^.dwLineNameSize > 500 then LDC^.dwLineNameSize := 500;
          FillChar(aName, SizeOf(aName), #0);
          StrLCopy(aName,PAnsiChar(LDC)+LDC^.dwLineNameOffset,LDC^.dwLineNameSize);
          ComboBox1.Items.Add( aName );
        end;
        Ln := LDC^.dwTotalSize;
        FreeMem( LDC, Ln );
      end;
    end;
    R := lineShutdown( Luh );
  end;
end;


Grüße von der Nordsee

Peter
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Di 02.12.14 19:49 
Laut Dokumentation bedeutet Rückgabewert 0 von lineGetDevCaps success, wäre also korrekt. Die Informationen stehen dann doch in dem vorher reserviertem Buffer. Wie ist denn dein TLineDevCaps definiert? Wenn dwTotalsize zu klein ist, sollte ein LINEERR_STRUCTURETOOSMALL kommen.
Du könntest natürlich beim ersten Aufruf stets eine Dummy-Structur übergeben, die nur die 2 DWORDS totalsize und neededsize enthält. Dann wird immer LINEERR_STRUCTURETOOSMALL fliegen, aber du weisst dann, wie groß der buffer sein muss, entsprechend alloziieren und lineGetDevCaps dann damit ein zweites mal aufrufen. Du solltest übrigens evtl. dann vorm Zugriff auf das record prüfen, ob das feld überhaupt existiert. Wenn das programm sonst mit einer alten API-Version läuft oder so, fliegt eine access-Violation. Oder wenigsten immer mindestens sizeof(TLineDevCaps) alloziieren.
OlafSt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 486
Erhaltene Danke: 99

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Mi 03.12.14 11:29 
Dieses Vorgehen, erstmal einen evtl. zu kleinen Buffer vorzugeben und sich somit die tatsächlich erforderliche Größe zu holen, ist üblich in der WinAPI. Man findet in so ziemlich allen Bereichen solche Strukturen mit einem "dwNeededSize"- Element darin.

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 03.12.14 12:12 
Hallo Boldar, hallo OlafSt,

Dank euch für die Antworten. Hatte mein Unverständniss wohl ungenau formuliert. Bei den ersten Versuchen erhielt ich den Code für zu wenig Speicher. Später, als ich die Speicherverwaltung im Griff hatte, war der Fehlercode 0 und ich konnte nur "dwTotalSize" mit "dwNeededSize" vergleichen. Zuvor hatte nur auf Fehler geprüft und den "LINEERR_STRUCTURETOOSMALL" erhalten. Beim ersten Aufruf ist die Struktur zu klein und die Größe in "dwTotalSize" eingetragen, sollte also einen Fehler ergeben. Dieses unterschiedliche Verhalten kann ich mir nicht erklähren.

Grüße von der Nordsee

Peter
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Mi 03.12.14 12:33 
Ich weiß nicht, warum ich dir eigentlich meinen kompletten Quellcode zur Verfügung stelle, wenn du dann da nicht einfach reinschaust.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
  
  apLineDevCaps := AllocMem(SizeOf(TLineDevCaps)); // Speicher reservieren
  apLineDevCaps^.dwTotalSize := SizeOf(TLineDevCaps);
  lineGetDevCaps(hLineApp, dwDeviceID, lpdwAPIVersion, 0, apLineDevCaps);
  if apLineDevCaps^.dwNeededSize > apLineDevCaps^.dwTotalSize then
  begin
    ReallocMem(apLineDevCaps, apLineDevCaps^.dwNeededSize); // Speicher reicht nicht, dann neu reservieren
    apLineDevCaps^.dwTotalSize := apLineDevCaps^.dwNeededSize;
    lineGetDevCaps(hLineApp, dwDeviceID, lpdwAPIVersion, 0, apLineDevCaps);
  end;
  if (apLineDevCaps^.dwMediaModes and LINEMEDIAMODE_INTERACTIVEVOICE) <> 0 then
  begin
    if apLineDevCaps^.dwLineNameSize > MAXAD then apLineDevCaps^.dwLineNameSize := MAXAD;
    FillChar(aName, SizeOf(aName), #0);
    StrLCopy(aName,PAnsiChar(apLineDevCaps)+apLineDevCaps^.dwLineNameOffset,apLineDevCaps^.dwLineNameSize);
    Result := IntToStr(apLineDevCaps^.dwPermanentLineID) + '=' + aName; // DeviceID und Name zurückgeben
  end;
  FreeMem(apLineDevCaps); // Speicher freigeben
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Do 04.12.14 11:46 
Hallo baumina,

ich habe wohl gesehen wie Du es programmiert hast und auch im Buch ist es so programmiert, auch ich habe es so programmiert. Die Frage war nicht wie kriege ich es zum Laufen sondern warum erhalte ich mal den Fehlerkode "LINEERR_STRUCTURETOOSMALL" und ein anderes mal "0"="Ok". Das erscheint mir nicht logisch! Wenn ich "LINEERR_STRUCTURETOOSMALL" immer erhalte, wenn "dwTotalSize < dwNeededSize" dann wäre es logisch! doch diesen Wert habe ich nur bei meinen ersten Versuchen erhalten.

Dabei hatte ich die Variable so deklariert:"LDC : TLineDevCaps;" und mit "@LDC" übergeben. Der Rückgabewert war "LINEERR_STRUCTURETOOSMALL". Später habe ich sie mit "LDC : PLineDevCaps;" deklariert und der Rückgabewert war "0". Das ist es was ich gern verstehen würde!

Grüße von der Nordsee

Peter