![]() |
WM_COPYDATA & Array of Strings = Müll
Hi,
ich habe da mal ein Problemchen an dem ich schon den ganzen halben Tag sitze, und das Problem ist das "Verschicken" eines dyn. Array of String. Ich habe schon ein paar Varianten durch die leider nicht funktionieren wollen. Beispel:
Delphi-Quellcode:
Leider kommt beim Empfänger immer nur Müll an.
type
TParamList = array of string; // --- Sender --- //... hMainFormWnd := FindWindow('TForm1', 'Test - Application'); //... begin if hMainFormWnd <> 0 then begin CPData.dwData := 0; CPData.cbData := sizeof(ParamList); CPData.lpData := @ParamList[0]; SendMessage(hMainFormWnd, WM_COPYDATA, WPARAM(Application.Handle), LPARAM(@CPData)); end; end; //... // --- Empfänger ---- procedure TForm1.WMCopyData(var Msg: TWMCopyData); var aParamList: TParamList; i, len, size: integer; begin len := Msg.CopyDataStruct^.dwData; //size := Msg.CopyDataStruct^.cbData; Setlength(aParamList, len); aParamList := TParamList(Msg.CopyDataStruct^.lpData); for i := 0 to len-1 do ListBox1.Items.Add(aParamList[i]); end; |
Re: WM_COPYDATA & Array of Strings = Müll
Intern ist ein String doch auch nur ein Zeiger auf Speicherbereich und enthält noch zusätzlich die Länge des Strings ... Nehm mal ein array of char.
Zumindest hatte ich das Problem bei der Implementierung von IPC über NamedPipes. |
Re: WM_COPYDATA & Array of Strings = Müll
Ich würde das ganze über einen Memorystream lösen.
Schreiben: 1. Länge des Strings als 4-Byte-Integer in den Stream schreiben 2. Den Inhalt des Strings 3. In die Copydata-Struktur die Länge des Streams (Stream.Size) sowie die Adresse (Stream.Memory) 4. WM_COPYDATA-Message verschicken Lesen: 1. MemoryStream instanitiieren und Zeiger zuweisen 2. 4-Byte Integer lesen und einen String mit SetLength (String, Länge) alloziieren 3. <Länge> Bytes aus dem Stream in den String lesen 4. Freuen, das es so einfach ist |
Re: WM_COPYDATA & Array of Strings = Müll
Isch abe garkeine TMemoryStreame. ;) ( Wäre ja zu einfach.)
Bald geb ichs auf und neme ein statisches Array. :( |
Re: WM_COPYDATA & Array of Strings = Müll
Zitat:
|
Re: WM_COPYDATA & Array of Strings = Müll
Mehr oder weniger für nonVCL optimiert. Daher keine Classes.
|
Re: WM_COPYDATA & Array of Strings = Müll
Hallo,
1. Strings mit Längenangabe sind Pascal-spezifisch, gibts in C usw. nicht. 2. Variable Strings sind Delphi-spezifisch... 3. Variables Array mit variablen Strings gibts in anderen Sprachen dreimal nicht. Und überhaupt sind Daten, die aus einem Zeiger und vom System dynamisch verwaltetem Speicher bestehen zum Datenaustausch herzlich ungeeignet. Für alle Programmierer ausser Delphianer wären nullterminierte C-Strings die natürliche Datenform und als Array eine Folge davon mit Doppel-0 als Abschluss. So arbeitet WIN32 intern und auch Copydata dürfte damit keine Probleme haben. Ich verwende daher für den Verkehr mit der Aussenwelt gleich PChar oder wandle bei Bedarf um, anstatt mich mit TStrings u.ä. zu verrenken. Gruss Reinhard |
Re: WM_COPYDATA & Array of Strings = Müll
Um den Code mal mit Zahlen auszudrücken:
Zitat:
@ParamList[0]: zeigt auf den ersten Zeiger auf einen String => Du kopierst die Zeiger von deinem Adressraum in Zeiger im anderen Adressraum, wo sie ins Nirvana zeigen. Die eigentlichen Stringdaten werden hierbei nicht kopiert. Ein array of string ist (grob beschrieben) nichts anderes als:
Delphi-Quellcode:
was wiederum (grob beschrieben) nichts anderes ist als
type
PStringArray = ^TStringArray TStringArray = array[0..MaxInt div SizeOf(Pointer) - 1] of string
Delphi-Quellcode:
Und wenn du das an WM_COPYDATA übergibst, werden halt nur die Zeiger statt der Daten kopiert. Also ist ein MemoryStream wohl die einfachste Variante das Problem zu lösen. Oder du schickst die Strings einzeln rüber.
type
PStringArray = ^TStringArray TStringArray = array[0..MaxInt div SizeOf(Pointer) - 1] of PChar |
Re: WM_COPYDATA & Array of Strings = Müll
Bei Copydata gibst Du einen Speicherbereich und eine Länge an. Wie Du die Daten dort hineinschreibst, bleibt dir überlassen. Wenn es nur ein einziger String ist, dann geht das so:
Delphi-Quellcode:
Wenn man mehr verschicken will, z.B. Strukturen, muss man die irgendwie serialisieren. Dazu könnte man dann neben Memorystreams auch sowas wie JSON oder XML verwenden, beide sind Standards, wobei JSON weniger Footprint / Overhead erzeugt. Aber, ach, dann wächst die Anwendung ja wieder um ein paar Kb. Und das geht bei nonVCL ja nun wirklich nicht. :stupid: Heutzutage programmiert man ja auch wie vor 40 Jahren, oder wie ein C-Eremit. :roll:
CPData.dwData := 0;
CPData.cbData := Length (MyString); CPData.lpData := @MyString[1]; SendMessage(hMainFormWnd, WM_COPYDATA, WPARAM(Application.Handle), LPARAM(@CPData)); Aber eine Fräge hätt ich nöch: Wenn nonVCL sich auf die Visual Control Library bezieht, wieso verzichtest Du dann auf TMemoryStream? MemoryStreams sind doch nun wirklich unsichtbar. Non-Visuell sozusagen... :gruebel: |
Re: WM_COPYDATA & Array of Strings = Müll
"C-Eremit." :lol:
Naja, MemoryStream könnte ich mir batsteln aber dann bräucht ich mich ja nicht mer mit dem "array of string" herumärgern. Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:48 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