Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Speicherverwaltung
Peter18 - Mo 01.12.14 17:15
Titel: Speicherverwaltung
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 - 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 - 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.
Peter18 - 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 - 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 - 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:
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; 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..500] of AnsiChar;
begin Lo := $00010003; Hi := $00030000; R := -2; H := unassigned;
FillChar(Par, SizeOf(Par), 0); R := lineInitialize( @Luh, HInstance, @LineCallBack, PChar( 'Test' ), DC ); if R = 0 then begin for I := 0 to DC-1 do begin R := lineNegotiateAPIVersion( Luh, I, Lo, Hi, V, LeId ); 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 - Di 02.12.14 19:49
Laut Dokumentation [
http://msdn.microsoft.com/en-us/library/ms735735%28v=vs.85%29.aspx] 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 - 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.
Peter18 - 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 - 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.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| apLineDevCaps := AllocMem(SizeOf(TLineDevCaps)); apLineDevCaps^.dwTotalSize := SizeOf(TLineDevCaps); lineGetDevCaps(hLineApp, dwDeviceID, lpdwAPIVersion, 0, apLineDevCaps); if apLineDevCaps^.dwNeededSize > apLineDevCaps^.dwTotalSize then begin ReallocMem(apLineDevCaps, apLineDevCaps^.dwNeededSize); 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; end; FreeMem(apLineDevCaps); |
Peter18 - 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
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!