![]() |
Get(anyPointer) Verständnisfrage
Hallo,
ich experimentiere grad mit der Übergabe von Zeigern anstele von VAR Parametern und frage mich, wie ich das folgende erreichen kann:
Delphi-Quellcode:
Wenn ich die Prozedur selber definieren kann, könnte ich auch das hier schreiben:
procedure GetThis(pp: Pointer);
begin pp := value; end;
Delphi-Quellcode:
Wenn ich aber ein Interface nutze, sieht die Sache schon anders aus.
procedure GetThis(var pp: Pointer);
begin pp := value; end; Wie erreiche ich dann, das auch die obere Funktion den Wert übergibt. Gibt es da vielleicht eine Compiler-Option? Wenn ja, welche? Hier ist noch ein Testbeispiel zur Verdeutlichung, was ich meine:
Delphi-Quellcode:
Wenn ich hier GetStringByReference und GetPCharByReference aufrufe, dann klappt die Parameterübergabe.
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Label1: TLabel; Edit1: TEdit; Button1: TButton; Label2: TLabel; Label3: TLabel; lblShowString: TLabel; lblShowPChar: TLabel; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } FPChar: PChar; FString: String; public { Public-Deklarationen } procedure GetPChar(this: PChar); procedure GetString(this: String); procedure GetStringByReference(var this: String); procedure GetPCharByReference(var this: PChar); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var PCh: PChar; Str: String; begin FString := Edit1.Text; FPChar := PChar(FString); GetStringByReference(Str); lblShowString.Caption := Str; GetPCharByReference(PCh); lblShowPChar.Caption := StrPas(PCh); end; procedure TForm1.GetPChar(this: PChar); begin this := FPChar; end; procedure TForm1.GetPCharByReference(var this: PChar); begin this := FPChar; end; procedure TForm1.GetString(this: String); begin this := FString; end; procedure TForm1.GetStringByReference(var this: String); begin this := FString; end; end. Wenn ich jedoch die anderen beiden Prozeduren verwende, dann gibt GetString() gar nichts aus, Wert bleibt komplett unverändert, wie ich das auch bei CallByValue erwarte. GetPChar() gibt Datenmüll aus. Wie kann ich nun Pointer in der Form wie in GetPChar() erhalten? Wie gesagt, wenn ich ein Interface verwenden will/muss, dann kann ich die Deklaration nicht für mich passend ändern, das geht nur bei komplett eigener Defintion. |
AW: Get(anyPointer) Verständnisfrage
Hallo,
Deine Erklärung ist etwas verwirrend aber folgendes funktioniert gleich:
Delphi-Quellcode:
procedure Irgendwas1(var S: String);
begin S := FString; end; procedure Irgendwas2(S: PString); // oder statt PString einfach ^String begin S^ := FString; end; procedure TForm1.Button1Click(Sender: TObject); var test: String; begin Irgendwas1(test); Caption := test; Irgendwas2(@test); Caption := test; end; |
AW: Get(anyPointer) Verständnisfrage
Zitat:
Zitat:
Delphi-Quellcode:
nörgelt der Compiler. Man braucht schon einen benannten Typen.
S: ^String
|
AW: Get(anyPointer) Verständnisfrage
Und man sollte IIRC auch sicherstellen, dass der reservierte Speicherplatz, auf den der übergebene Pointer zeigt, ausreichend dimensioniert wurde, bevor man hineinschreibt.
|
AW: Get(anyPointer) Verständnisfrage
Zitat:
Delphi-Quellcode:
Ohne var werden keine Daten/werte aus der procedure zurück gegeben!
procedure irgendwas(wert:integer);
begin wert:=66; end; ... wert:=9; irgendwas(wert); // Hier ist wert immer noch 9 !!!!! Ausnahme:
Delphi-Quellcode:
weil Du eine Adresse übergeben hast und an diese Adresse Daten geschrieben wurden. Die Adresse ist daran aber nicht direkt beteiligt.
procedure irgendwas(pw:pinteger);
begin pw^:=100; end; ... wert:=45; irgendwas(@(wert); // ab hier ist wert=100; Gruß K-H |
AW: Get(anyPointer) Verständnisfrage
Zitat:
:gruebel: |
AW: Get(anyPointer) Verständnisfrage
Danke für Eure Mithilfe aber
bei mir klappt es noch nicht.
Delphi-Quellcode:
Ich erhalte immer noch Datenmüll als Rückgabe.
unit UPChar;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; Label1: TLabel; Button1: TButton; Label2: TLabel; lbOut: TLabel; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } FValue: String; public { Public-Deklarationen } procedure GetValue(p: PChar); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var pc: PChar; begin FValue := Edit1.Text; GetValue(@pc); lbOut.Caption := StrPas(pc); //Freemem(pc, Length(FValue) + 8 + 1); //Hier ungültige Zeifer Operation //wer slso gibt am Ende den Speicher wieder frei??? end; procedure TForm1.GetValue(p: PChar); begin getmem(p, Length(FValue) + 8 + 1); p := PChar(FValue); end; end. @Furtbichler: Wenn ich eine eigene Implementation wählen kann, übergebe ich sowas als call by reference. Wenn ich aber auf ein Interface zugreifen will/muss und der das Interface festgelegt hat hat eine Get Methode mit dem Übergabeparameter call by value definiert, dann habe ich leider keine Wahl, dann muss die Wertübergaben eben damit funktionieren. Ich habe dem PChar Parameter jetzt Speicher zugewiesen und dann erst den Wert übergeben. Dennoch erhalte ich Datenmüll. Ich hab mir mal interessehalber das OpenTools API angeschaut Zum Beispiel hier:
Delphi-Quellcode:
wollte ich dieses Interface verwenden, hätte ich keine Wahl. Für mich selber würde ich natürlich var Buffer: PChar definieren. Aber bei einem vorgegebenen Interface???
TIEditReader = class(TInterface)
public function GetText(Position: Longint; Buffer: PChar; Count: Longint): Longint; virtual; stdcall; abstract; end; Deshalb will ich auch hier die Parameterübergabe beherrschen. Get heißt für mich, Wert holen. Also muss das doch irgendwie gehen, sobald es sich bei dem Parameter um einen Zeiger handelt. Aber wie. Gibt es vielleicht eine Compileroption, die sagt, in diesem Fall keinen Stack FRame anlegen? Oder gibt es eine andere Lösung? Wie also kann ich aus der Methode GetValue() den PChar Wert erhalten, analog zur oben aufgeführten Interfacefunktion, die über den Buffer ihren Wert übergibt, obwohl Buffer dort nicht als VAR Parameter definiert ist. Speicher ist zugewiesen. Klappt auch dann bei mir noch nicht mit der Übergabe, wenn ich entweder sowohl innerhalb der Methode als auch in Button1Click Speicher zuweise und auch nicht, wenn ich das nur in Button1Click mache. Wenn also Compileroption, welche? (Delphi 7 oder 2006) |
AW: Get(anyPointer) Verständnisfrage
Wieso? Der Pointer (Buffer) wird nicht verändert. Er enhält eine Adresse, an der mindestens 'Count' Bytes reserviert sind. So. Du übergibst die Adresse und hinterher steht an der Adresse etwas drin. Die Adresse selbst wird nicht verändert. Also wird diese auch als 'Call by Value' übergeben. Wenn Du das nicht machen würdest, hast Du etwas nicht richtig verstanden.
So, nun zu deinem Code: Der Aufrufer reserviert Speicher, der von der aufgerufenen Methode gefüllt wird.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var pc: PChar; begin FValue := Edit1.Text; getmem(pc, Length(FValue) + 8 + 1); // DER AUFRUFER RESERVIERT DEN SPEICHER GetValue(pc); lbOut.Caption := StrPas(pc); ... FreeMem(pc, Length(FValue) + 8 + 1); // UND GIBT IHN WIEDER FREI ("Wer Müll macht, muss aufräumen") end; procedure TForm1.GetValue(p: PChar); begin Move (@FValue[1],p, SizeOf(FValue[0]) * Length(FValue)); // Verschiebe Bytes (1 Zeichen könnte auch 2 Bytes lang sein( end; |
AW: Get(anyPointer) Verständnisfrage
Danke! Muss mich aber erst mal mit Deiem Code beschäftigen.
Zitat:
Ich will doch gerade den Inhalt dieses Puffers lesen, sowohl mit der Methode GetValue wie es auch die IDE mit der Interface Methode TIEditReader macht. Wie ich Call by reference verstanden habe, wird doch dort der Wert an die Adresse übergeben, die mit dem VAR Parameter angegeben ist. Ich kann momentan zur obigen Übergabemethode keinen grundsätzlichen Unterschied erkennen, und richtig, ich habe noch nicht verstanden, warum im von mir betrachteten Fall call by value übergeben wird. Sonst übergebe ich call by value doch nur, wenn ich Werte an die Methode zur internen Verwendung übergeben will. In meinem Fall aber will ich den Wert von der Methode haben. |
AW: Get(anyPointer) Verständnisfrage
Zitat:
Ohne var werden keine Daten/werte aus der procedure zurück gegeben! Dann würde es umgekehrt gar nicht funktionieren, nämlich so hier: procedure irgendwas(aWert: PChar); begin aWert := PChar(AnyString); end; Dieses Ergebnis, das igendwas(@Wert) dann nicht funktioniert, erhalte ich auch. Nun aber habe ich in den ToolsAPI die schon geannte Funktion GetText(Position: Integer, Buffer: PChar; ... gefunden und dort scheint es anders zu sein. Zumindest geh ich davon aus, das Getxxx einen Wert holt, wie GetText(1, @wert, 15) mit ... GetText(Pos: Integer; Buffer: PChar; count: Integer) begin Buffer := PChar(AnyString); end; Wenn ich da falsch liege, müsste dann diese Funktion nicht Putxxx() doer Setxxx() heißen? Dieser Punkt ist es, der mich verwirrt. Oder es gint tatsächlich einen Weg, so einen Wert an Buffer zzu übergeben, nur wie, wenn meine Annahme richtig ist. Wie kommuniziert Delphi unter Verwendung dieser Funktion GetText()? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:20 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