Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Untyped Parameter var Buf (https://www.delphipraxis.net/151835-untyped-parameter-var-buf.html)

C0pa 3. Jun 2010 10:53


Untyped Parameter var Buf
 
Ola

Delphi-Quellcode:
function callbackSendTo(s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr; tolen: Integer): Integer; stdcall;
Das ist meine SendTo Methode, jetzt möchte ich den Inhalt von Buf als String zurück gegeben bekommen.
Derzeit mache ich das so:

Delphi-Quellcode:
var s: String;
s := PChar(@Buf);
Witzigerweise erhalte ich mal das richtige Ergebnis und mal nur das erste Byte. Kann jemand sagen was ich ändern muss?

Greez

himitsu 3. Jun 2010 10:59

Re: Untyped Parameter var Buf
 
Zitat:

Zitat von C0pa
Kann jemand sagen was ich ändern muss?

Nee.

Erstmal wäre es raktisch, wenn du verrätst, wie und mit welchen Werten diese Funktion aufgerufen wird,
eventuell eine Erwähnung der Delphiversionen und was du eigentlich als Ergebnis (in deinem String) erwartest.

eventuell mal so versuchen und das Len mit auswerten
Delphi-Quellcode:
SetString(S, @Buf, Len div SizeOf(Char));
ab Delphi 2009 S als AnsiString oder TRawByteString deklarieren und dann so
Delphi-Quellcode:
SetString(S, Buf, Len);
aber dennoch wäre es nicht schlecht, wenn man die Eingangswerte kennt, damit man darauf die passenste Lösung auswählen kann.

SirThornberry 3. Jun 2010 10:59

Re: Untyped Parameter var Buf
 
Durch den Cast auf PChar wird die #0 als Ende der Zeichenkette angesehen. Wenn also irgendwo innerhalb deines Buffers eine #0 ist wird alles dahinter ignoriert. Genauso kann es umgekehrt richtig krachen wenn am Ende deines Buffers keine #0 vorkommt weil dann über den Buffer hinaus gelesen wird um entsprechend eine #0 zu finden und da kann es zur Zugriffsverletzung kommen.
Bei deiner Methode wird mitgegeben wie lang der Buffer ist. Diese Angaben solltest du auch nutzen.
Bytes von einem zum anderen Ort kann man mit move und copymemory kopieren. Der Typ ist in beiden Fällen irrelevant (im Gegensatz zu deinem PChar)

[Edit]
Anstelle von "len" wäre die bessere Bezeichnung "size". Denn len steht für eine Anzahl an Elementen und da spielt es eine Rolle um welchen Typ es sich handelt was deinem Untyped Parameter widerspricht. Size hingegen gibt die Größe an und nicht die Anzahl der Elemente was somit bei Parametern deren Typ keine Rolle spielt zu bevorzugen ist.

C0pa 3. Jun 2010 11:10

Re: Untyped Parameter var Buf
 
Habe mir eine Funktion jetzt geschrieben:

Delphi-Quellcode:
function bufferToString(var Buf; Len: Integer): String;
var
  a: array of Byte;
  i: Integer;
begin
  SetLength(a, Len);
  for i := 0 to Len do
    a[i] := PByte(Cardinal(@pchar(buf)) + i)^;
  Result := String(a);
end;
Die Funktioniert wunderbar.

SirThornberry 3. Jun 2010 11:25

Re: Untyped Parameter var Buf
 
dein + i kann glaub ich schief gehen. Denn je nachdem wie PChar in Unicodeversionen definiert ist wird dann um mehr als ein Zeichen weiter gerückt. Verwende doch einfach move oder copymemory

thkerkmann 3. Jun 2010 11:31

Re: Untyped Parameter var Buf
 
Also ehrlich, man kann's echt übertreiben.

Da gab's doch schon mal so'ne Diskussion mit Zahlen..... :gruebel:


SetString hätte es echt getan, und kostet so gut wie nix.

Gruss

himitsu 3. Jun 2010 11:38

Re: Untyped Parameter var Buf
 
würde dann Bytegenau in Chars umkopieren (auch unter Unicode / ab Delphi 2009)
Delphi-Quellcode:
function bufferToString(var Buf; Len: Integer): String;
var
  i: Integer;
begin
  SetLength(Result, Len);
  for i := 0 to Len - 1 do
    Result[i + 1] := Chr(PByte(@buf)[i]);
end;
würde den Puffer als ANSI ansehn (und ab Delphi 2009 dieses nach Unicode konvertieren)
Delphi-Quellcode:
function bufferToString(var Buf; Len: Integer): String;
var
  S: AnsiString;
  i: Integer;
begin
  //SetLength(S, Len);
  //for i := 0 to Len - 1 do
  //  S[i + 1] := PAnsiChar(@buf)[i];
 
  //SetLength(S, Len);
  //Move(Buf, S[1], Len);  // optimiertes Kopieren

  SetString(S, @Buf, Len); // oder eben Alles in Einem

  Result := S;
end;
Wie gesagt, ohne Kenntnis der Lage (Eingangswerte, System und Wunschvorstellung über Ausgabewerte)
kann man einfach nix Genaueres sagen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:13 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