kurze fragen zu wm_copydata delphi<>lazarus?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von laz847 »

Hallo Leute,

ich versuche gerade ein Beispiel aus Delphi in Lazarus umzusetzen: http://delphi.about.com/od/windowsshell ... pydata.htm

Code: Alles auswählen

 
  TCopyDataType = (cdtString = 0, cdtImage = 1, cdtRecord = 2);
 
  TSampleRecord = packed record
    s : string[50];
    i : integer;
    d : TDateTime;
  end;
 
  TWMCopyData = packed record
   Msg: Cardinal;
   From: HWND;                      // Handle of the Window that passed the data
   CopyDataStruct: PCopyDataStruct; // data passed
   Result: Longint;                 // Use it to send a value back to the "Sender"
  end;   
 
procedure TForm1.HandleCopyDataRecord(copyDataStruct: PCopyDataStruct);
var
  sampleRecord : TSampleRecord;
begin
  sampleRecord.s := TSampleRecord(copyDataStruct.lpData^).s;
  sampleRecord.i  := TSampleRecord(copyDataStruct.lpData^).i;
  sampleRecord.d := TSampleRecord(copyDataStruct.lpData^).d;
  Memo1.Lines.Add(Format('Received record at %s',[DateToStr(Now)]));
  Memo1.Lines.Add(Format('sampleRecord.s = %s',[sampleRecord.s]));
  Memo1.Lines.Add(Format('sampleRecord.i = %d',[sampleRecord.i]));
  Memo1.Lines.Add(Format('sampleRecord.d = %s',[DateToStr(sampleRecord.d)]));
end; 
Die Zeile

Code: Alles auswählen

sampleRecord.s := TSampleRecord(copyDataStruct.lpData^).s; 
erzeugt folgenden Fehler:

unit_server.pas(129,50) Error: Illegal qualifier

Wie wird das korrekt geschrieben?

-------------------------------------

COPYDATASTRUCT aus der struct.inc??? was ist das denn?

Code: Alles auswählen

 
  COPYDATASTRUCT = record
          dwData : ULONG_PTR;
          cbData : DWORD;
          lpData : PVOID;
       end;
     tagCOPYDATASTRUCT = COPYDATASTRUCT;
     TCOPYDATASTRUCT = COPYDATASTRUCT;
     PCOPYDATASTRUCT = ^COPYDATASTRUCT;   
 

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von theo »

Wie immer, erklär doch mal bitte, was du erreichen möchtest.
Solche "Windows-ismen" sind "unlazarusisch" ;-)
Manchmal gibt es für so etwas eine Cross-Plattform Lösung.

Könnte das z.B. in deine Richtung gehen?
http://lazarus-ccr.sourceforge.net/docs ... lient.html
http://www.freepascal.org/docs-html/fcl ... erver.html

laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von laz847 »

Jaja Theo :) Du liegst schon ganz richtig, Du warst ja auch schon in meinen anderen Threads aktiv, ich danke Dir :)!

Mein Ziel, ich muss eine stabile Kommunikation zwischen dem Client (lazarus DLL, in Metatrader MT4) zu meinem Programm (ebenfalls lazarus) herstellen. Über diese Verbindung - nur lokal also beide auf einem Rechner/in einem Verzeichnis - möchte ich in beide Richtungen kurze Strings senden, da reichen 255 Zeichen. Ich muss aber auch Arrays, bzw. Packed Records (diese werden vom MT4 mit & per Referenz an die dll übergeben) aus dem der DLL an den Server übergeben. Dazu hatte ich mir LNet installiert, den Client in die dll gepackt und den Server in meine Software.

Strings per TCP zu senden geht schon, nur mit den Records kam ich nicht klar, habe mir die in einen Memorystream geschrieben, einen eigenen Header davor aber beim Server war ich nicht in der Lage den Stream zusammenzubauen. Ausserdem fiel mir auf, das es nicht sonderlich schnell ist. Nun habe ich zufällig dieses Beispiel gefunden und rechne mir aus, das die Übertragung der Daten mit WM_COPYDATA schneller sein dürfte?

Für die normale Kommunikation würde ich TCP nutzen, nur die Records, bzw. Arrays die zum Server gesendet werden, sollen möglichst mit max. Speed ankommen, es handelt sich um grössere Datenmengen > 100.000 kleine Datensätze die ausgewertet werden müssen.

Und falls niemand eine bessere Idee hat, wäre es nett wenn mir jemand sagen könnte wie das hier in FP aussehen müsste:

Code: Alles auswählen

 sampleRecord.s := TSampleRecord(copyDataStruct.lpData^).s;
  sampleRecord.i  := TSampleRecord(copyDataStruct.lpData^).i;
  sampleRecord.d := TSampleRecord(copyDataStruct.lpData^).d;
Wenn ich die 3 Zeilen raus hab kompiliert er, es liegt also nur noch daran ;)

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von theo »

Und was spricht nun gegen SimpleIPC?
laz847 hat geschrieben: Und falls niemand eine bessere Idee hat, wäre es nett wenn mir jemand sagen könnte wie das hier in FP aussehen müsste:
Ich habe es nicht getestet, bin auf Linux, aber du brauchst ja nur der Deklaration folgen.

Code: Alles auswählen

 copyDataStruct: PCopyDataStruct
Also ist copyDataStruct ein Zeiger auf COPYDATASTRUCT (unglücklich, ich würde die Variable anders nennen).
D.h. an COPYDATASTRUCT kommst du mit copyDataStruct^ ran, also dereferenzieren.
Wahrsch. also so:

Code: Alles auswählen

TSampleRecord(copyDataStruct^.lpData^).s;

laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von laz847 »

Na eigentlich spricht nichts gegen IPC, wenn ich wüsste wie das geht, ich suche seit ca. 2 Wochen einen Weg und wenn ich etwas google sind die Links schon alle als gelesen markiert :D. Irgendwie ist dieser Bereich nur sehr mager dokumentiert und als Anfänger ist es echt schwer etwas - das dann auch funktioniert - zu finden. Wenn man erstmal ein funktionierendes Beispiel oder wenigstens vernünftige Erklärungen hat gehts ja, ging ja mit lNet auch :).

Aber was denkst Du über die Performance, welcher Weg der Übertragung ist der schnellste? Da ich mir die Kommunikation während einer Datenübertragung nicht unterbrechen will/kann spricht eigentlich viel dafür, die Datenübertragung extra zu gestalten? Wie gesagt die normale Kommunikation per Strings geht ja schon, ich muss jetzt nur noch die Übertragung grösserer Datenmengen realisieren dann ist der Part erledigt :).

2 Fragen noch...

Auf der Seite im Beispiel wird "Handle" verwendet, ich sehe jedoch nicht woher das kommt, kompiliert doch noch nicht, was soll das sein? Hast Du/jemand eine Idee?

Code: Alles auswählen

FindWindow(PChar('TReceiverMainForm'),PChar('ReceiverMainForm')) ;
res := SendMessage(receiverHandle, WM_COPYDATA, Integer(Handle), Integer(@copyDataStruct)) ;
Und sag mal wenn das Pointer sind, soweit ich weiß gehen doch Pointer nur innerhalb der selben Anwendung oder? Geht das dann so überhaupt das die Dll das per Pointer kopiert?

Dein Tipp geht schon mal riesen Danke :lol: :lol: :lol: :lol:

PS: Handle ist wohl das Handle der sendenden Software? Damit hab ich ein Problem mehr, da dort wahrscheinlich nicht das Handle der dll reingehört sondern des MT4 in welchem diese geladen ist oder?

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von theo »

laz847 hat geschrieben:Na eigentlich spricht nichts gegen IPC, wenn ich wüsste wie das geht,
Weiss auch nicht mehr auswendig. Probier's halt aus, so viele Eigenschaften haben die Komponenten nicht.
laz847 hat geschrieben: Auf der Seite im Beispiel wird "Handle" verwendet, ich sehe jedoch nicht woher das kommt, kompiliert doch noch nicht, was soll das sein? Hast Du/jemand eine Idee?
Ja, ich habe eine Idee: Lies das Zeug richtig. Da ist ein Zeilenumbruch drin:

Code: Alles auswählen

receiverHandle := 
FindWindow(PChar('TReceiverMainForm'),PChar('ReceiverMainForm')) ;
Aber ich würde TSimpleIPCClient und TSimpleIPCServer verwenden. Da wird in der Win Version intern wahrsch. auch CopyData verwendet.

laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von laz847 »

Ok ich schau mir IPC nochmal an, geht das auch in einer dll? Nicht das da wieder sonstwas fürn Aufwand nötig ist das ohne Form zum laufen zu bekommen, bei lNet müssen im NonVcl Client (der dll) extra Callbacks im Loop eingerichtet werden, damit Nachrichten empfangen werden können. Und wie gesagt, ich habe lNet am laufen und kann damit Strings senden, nur eben keine Streams, bzw. bekomme ich es irgendwie nicht hin einen Stream darüber zu senden.

res := SendMessage(receiverHandle, WM_COPYDATA, Integer(Handle), Integer(@copyDataStruct)) ;

Sorry mein Fehler, hab mich blöd ausgedrückt, es ging um das markierte Handle. Das kommt wohl normalerweise von TForm1.functionsname, da ich in der dll keine Form habe und diese noch in dem Prozess des MT4 läuft weiß ich da gerade nicht weiter und bin am lesen. Kompiliert zwar, die dll findet auf den Empfänger über den Fenstertitel aber im Empfänger tut sich nichts.

Ich verstehe das Du IPC empfielst aber wie gesagt, die normale Kommunikation kann ich ja über TCP machen, das hab ich doch schon, läuft und funktioniert super. Ich muss nur die grossen Arrays bzw. Records noch auf einem guten Weg in den Empfänger bekommen. Meinst Du nicht es ist sinnvoller für so etwas Memory Mapped Files oder Pipes zu verwenden oder eben WM_COPYDATA?
For local exchange, transfer rate is truly amazing - almost 3 gigabytes per second. This means that named pipes can be used to transfer almost any amount of data into MQL5 programs.
http://www.mql5.com/en/articles/503

Hier sind noch Links zu anderen Beispielen, da fehlt mir aber immer der Lazarus Part dazu und ich finde nichts Verwendebares, wie gesagt dieses Thema ist nicht so umfassend dokumentiert. Wenn jemand z.B. wüsste wie ich das mit NamedPipes realisieren kann wäre das der Hammer. Ich finde nur wenig dazu, ich bin wie gesagt vor kurzem erst von MQL4 zu Lazarus gesprungen und hab nur ganz alte Delphi Erfahrungen ;)...

http://www.forexfactory.com/showthread. ... ost4372428
http://www.mql5.com/en/articles/115

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von theo »

Sei mir nicht böse, aber du bist ein ziemlicher schwieriger Kunde.

Was soll das heissen, "Ich kann über LNet keine Streams senden"? Stattdessen grübelst du an irgend einen noch viel komplizierteren Zeug rum?
Ich kenne mich zwar mit LNet nicht speziell aus, aber einen Stream oder Datenblock kann man mit jeder TCP Komponente senden, das ist deren Job.
Warum versuchst du nicht, das hinzukriegen?
Wie es mit Synapse geht habe ich dir ja schon geschrieben.

laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von laz847 »

Lach nein bin nicht böse, dass weiß ich, dass liegt daran das ich mich auf Neuland bewege und schon soviel probiert hab das ich ziemlich verzweifelt bin. Jedes Mal taucht ein anderes Problem auf und ich muss wieder umdenken und fange von vorn an.

"Ich kenne mich zwar mit LNet nicht speziell aus, aber einen Stream oder Datenblock kann man mit jeder TCP Komponente senden, das ist deren Job. Warum versuchst du nicht, das hinzukriegen?"

Hab ich wirklich, keine Ahnung wenn ich den Stream direkt am Clienten wieder ausgepackt habe ging es, ich konnte meinen Header lesen und den Datenteil sauber entpacken, kam das über TCP war aber schon zu sehen das da was verschoben war. Hatte an 1 ein @ um zu erkennen ob Streams oder Strings kommen. Wenn ich den Stream im Editor geöffnet habe, standen da Dinge drin die überhaupt nicht reingehörten, wie zB der Name der Logdatei :D. Ich konnte den orginal Stream aber wie gesagt vorm Senden ohne Probleme entpacken, die Headergösse abgezogen blieb der Datenteil übrig, ich hab kein Plan wieso das dann nicht mehr ging, hab stundenlang geloggt, gesucht und rumprobiert.

Wenn Du mir behilflich wärst, ich habe noch einen Thread offen wo es um die Datenübertragung geht? Dann würde ich da mal reinwerfen was ich noch habe, evtl. fällt Dir ja was auf warum das nicht ging?

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von theo »

Du musst deine Daten auf den Stream serialisieren.
Man kann natürlich nicht irgendwelche Pointer draufpacken, sondern muss die Daten "draufschreiben".
Auch ein AnsiString eines Record ist z.B. ein Pointer!!
Vllt. hat es daran gelegen.

laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von laz847 »

Ja das klingt als wenn Du in die richtige Richtung denkst, ich hab in der Richtung auch vermutet das da etwas nicht stimmt, allerdings gabs dann dauernd Exceptions beim Versuch direkt in den Stream zu schreiben.

Ich räume mal auf und versuch das nochmal nachzustellen was ich da versucht habe, dann mache ich einen Thread gezielt dafür auf. Ich muss jetzt langsam einen Weg finden, sonst werde ich noch irre, hätte nicht gedacht das es so schwierig wird :evil:

Lieben Dank :roll:

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: kurze fragen zu wm_copydata delphi<>lazarus?

Beitrag von theo »

laz847 hat geschrieben:Ja das klingt als wenn Du in die richtige Richtung denkst, ich hab in der Richtung auch vermutet das da etwas nicht stimmt, allerdings gabs dann dauernd Exceptions beim Versuch direkt in den Stream zu schreiben.
Dann mach mal ein Beispiel, wie du das angestellt hast.
Tipp: Man kann keinen TStream (abstrakte Basisklasse) instanziieren sondern muss eine Ableitung nehmen, also TMemoryStream, TFileStream, TStringStream...

Antworten