Autor |
Beitrag |
Sprotti
      
Beiträge: 26
|
Verfasst: Di 26.08.08 13:15
Hallo,
ich habe mir ein packed record zusammengestellt in dem ich meine Daten schön ordentlich aufliste.
Delphi-Quelltext 1: 2: 3: 4: 5:
| TMyRecord = packed record bla : Integer; blub : Byte; thing : array[0..4] of Longword; end; |
Dieses record hätte ich jetzt gerne zur Übergabe an folgende function als array of byte.
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:
| function TMyClass.PutGetAByteArray(var myarray:array of byte); begin if myarray[2]=0 then myarray[2]:=5; end;
function TMyClass.ConvertRecordToArray():Boolean var aRecord:TMyRecord; anArray:array of Byte; begin ...
PutGetAByteArray(anArray);
if bla=$0050 then Result:=true; end; |
könnt Ihr mir bitte helfen die Konvertierungen richtig hizukriegen?
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 26.08.08 13:32
Moin!
Da muss man normalerweise nix "umwandeln", die Daten liegen ja bei einem packed record eh schon "richtig" im Speicher, eigentlich musst du nur die Adresse der record-Instanz nehmen und gut.
Vielleicht erklärst du mal kurz, was das werden soll, dann ist es leichter, was dazu zu sagen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Sprotti 
      
Beiträge: 26
|
Verfasst: Di 26.08.08 14:03
Titel: Methode braucht Parametertyp
Ich habe eine SendReceive Methode, die zum Versenden so ein bytearray annimmt und die Antwortdaten in das gleiche Array packt. Ich möchte das record nutzen um die Bytes im Array ihrer Bedeutung im record zuzuweisen.
Beim Aufruf der Methode wird aber das record natürlich nicht als übergabetyp akzeptiert
Fehlermeldung des Compilers:inkomptible Typen Array und TMyRecord
Ich habe array of byte als übergabetyp gewählt um verschiedene records mit der sendreceive methode verschicken zu können und nicht für jeden neuen TMyXYRecord eine neue versandmethode schreiben zu müssen
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 26.08.08 15:23
Titel: Re: Methode braucht Parametertyp
Moin!
Sprotti hat folgendes geschrieben: | Ich habe eine SendReceive Methode, die zum Versenden so ein bytearray annimmt und die Antwortdaten in das gleiche Array packt. |
Zeig doch mal diese Methode, damit man zum Einen die Parameterliste sieht und zum Anderen das mit dem "Antwort in das gleiche Array packt" mal etwas näher unter die Lupe nimmt - da gibt´s nämlich diverse Probleme, die nicht so leicht zu lösen sind.
Sprotti hat folgendes geschrieben: | Ich möchte das record nutzen um die Bytes im Array ihrer Bedeutung im record zuzuweisen. |
Es scheint also um Netzwerkkommunikation zu gehen, richtig? In diesem Fall sind records als Transportcontainer überhaupt keine gute Idee...  Das solltest du evtl. nochmal überdenken.
Sprotti hat folgendes geschrieben: | Ich habe array of byte als übergabetyp gewählt um verschiedene records mit der sendreceive methode verschicken zu können und nicht für jeden neuen TMyXYRecord eine neue versandmethode schreiben zu müssen |
Unter Anderem ist genau das ein Grund, gleich ganz auf die records bei der Kommunikation zu verzichten.
Statt einem array of Byte wäre hier aber vermutlich ein einfacher Pointer besser. Aber das kann man erst vernünftig klären, wenn man die oben angesprochene Methode mal gesehen hat.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Sprotti 
      
Beiträge: 26
|
Verfasst: Di 26.08.08 15:55
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 26.08.08 16:58
Moin!
Sprotti hat folgendes geschrieben: | Delphi-Quelltext 1: 2: 3: 4:
| function TMyClass.PutGetAByteArray(var myarray:array of byte); begin transcryptor.SendReceiveData(myarray); end; | |
OK, das bringt nun wirklich nicht viel weiter...
Sprotti hat folgendes geschrieben: | Von der Zielklasse ist nur die Deklaration vorhanden
Delphi-Quelltext 1:
| function TTransCrypt.SendReceiveData(var Data:array of byte):Longword; | |
Heißt: die Komponente/Klasse ist nicht von dir und du hast auch keinen Quelltext?  Das wäre doof...
Sprotti hat folgendes geschrieben: | Aber ist denn diese Information wirklich notwendig um eine Möglichkeit zu finden ein record in ein array of byte typ zu konvertieren? |
Jain, ein entscheidender Aspekt der ganzen Sache ist folgender: du übergibst nur einen Zeiger auf einen Speicherbereich (ob das nun als record oder als array of Byte oder PChar oder was auch immer ist, spielt keine Geige), aber woher weiß die Funktion/Methode, wieviele Daten zu bearbeiten sind bzw. wie groß der übergebene Speicherblock ist?!  Das kann übel ins Auge gehen, wenn man Speicher überschreibt, der einem nicht gehört.  Deshalb wollte ich mal einen Blick auf die Kommunikations-API-Anbindung werfen, um herauszufinden, wie solche Probleme behandelt werden (oder ob überhaupt).
Aber gut, um die Frage endlich mal zu beantworten: es geht mit einem Typecast:
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:
| type TTestRec = packed record T1, T2: Integer; end; TByteArray = array of Byte;
function PutGetAByteArray(var myarray: array of byte): Longword; begin ShowMessage(IntToHex(myarray[0],2)+ IntToHex(myarray[1],2)+ IntToHex(myarray[2],2)+ IntToHex(myarray[3],2)+#13+ IntToHex(myarray[4],2)+ IntToHex(myarray[5],2)+ IntToHex(myarray[6],2)+ IntToHex(myarray[7],2)); end;
procedure TForm1.Button1Click(Sender: TObject); var test: TTestRec; p: Pointer; begin test.T1 := $12345678; test.T2 := $DEADBEEF; p := @test; PutGetAByteArray(TByteArray(p)); end; | Allerdings: ich würde dringend mal klären, wie das mit dem Längenproblem gelöst ist!  (und jetzt nicht einfach den Ansatz verwenden und vergessen - das gibt sonst mal später die grausigsten Fehler und Effekte, und keiner kann sich erklären, wie es dazu kommt...)
Sprotti hat folgendes geschrieben: | Die Records die ich nutze enthalten keine dynamischen Elemente. D.h. sie haben immer eine feste Größe und Struktur. |
Das ist schonmal gut - jedenfalls in deinem Fall.
cu
Narses
//EDIT: PByteArray in TByteArray geändert
_________________ There are 10 types of people - those who understand binary and those who don´t.
Zuletzt bearbeitet von Narses am Di 26.08.08 19:58, insgesamt 1-mal bearbeitet
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Di 26.08.08 19:14
? SendReceive sieht so aus als wenn daten übergeben werden und die ankommenen Daten wieder ins Array geschrieben werden.
Die Größe ist doch dann einfach mit Low() High() und Length() bzw SizeOf() bestimmbar.
So sollte es gehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| rec: TMyRecord ; bla: array of Byte; begin SetLength(bla, SizeOf(rec)); CopyMemory(@bla[0], @rec, SizeOf(rec)); SendReceiveData(bla); |
sollte die Funktion aber von dir sein (SendReceiveData) dann würd ich die aber auch abändern
PS: ähm ja, ich behaupte jetzt einfach mal nen var bla array of byte und nen pbytearray passen nicht zusammen, oder irre ich mich jetzt total?
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 26.08.08 20:04
Moin!
uall@ogc hat folgendes geschrieben: | ? SendReceive sieht so aus als wenn daten übergeben werden und die ankommenen Daten wieder ins Array geschrieben werden. |
Das hat er ja schon gesagt, geht ja auch aus dem Namen hervor. Interessanter dürfte aber wohl sein, was da genau passiert.
uall@ogc hat folgendes geschrieben: | Die Größe ist doch dann einfach mit Low() High() und Length() bzw SizeOf() bestimmbar. |
Ist das so?  Wer sagt, dass die aufgerufene Funktion eine Delphi-Funktion ist, die auf den Delphi-MemManager Zugriff hat?  Oder hab ich da was falsch verstanden?  Genau genommen kommt da nur ein Pointer an, keine Länge (schließlich wollen die API-Funktionen ja nicht aus Spaß eine Bufferlänge haben).
uall@ogc hat folgendes geschrieben: | So sollte es gehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| rec: TMyRecord ; bla: array of Byte; begin SetLength(bla, SizeOf(rec)); CopyMemory(@bla[0], @rec, SizeOf(rec)); SendReceiveData(bla); | |
Warum erst nochmal Speicher holen und die Daten kopieren? Die Adresse zu übergeben sollte doch wohl reichen (mein Code oben ist getestet, das funktioniert so, wie da angegeben).
uall@ogc hat folgendes geschrieben: | PS: ähm ja, ich behaupte jetzt einfach mal nen var bla array of byte und nen pbytearray passen nicht zusammen, oder irre ich mich jetzt total? |
Ja, ich habe da nicht genau genug hingesehen, hab´s in TByteArray geändert. Danke für den Hinweis.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Di 26.08.08 21:31
Dann hast du aber net ausfühlrich getestet. Ein "var x: array of byte" in einer Funktion sind in wirlichkeit zwei Parameter, @x und High(x).
Bei deiner Konvertierung geht zweites verloren -> length und high funktionieren nicht mehr (und auch SetLength).
Ob nun c++ oder Delphi hintersteckt ist egal, Delphi kann mit dem Array weiterarbeiten und es auch wieder verändern (SetLength).
Mache einfach mal folgenden Test (daher auch das Kopieren in ein extra Array):
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:
| type TMyRecord = packed record a, b: integer; end; TByteArray = array of byte;
procedure Test(var Param: array of byte); stdcall; begin MessageBoxA(0,PChar(Format('%d',[length(Param)])),nil,0); end;
procedure TForm1.FormCreate(Sender: TObject); var TestRecord: TMyRecord; P: Pointer; myarray: TByteArray; begin TestRecord.a := $12345678; TestRecord.b := $78563412; p := @TestRecord;
Test(TByteArray(p)); SetLength(myarray, SizeOf(a)); CopyMemory(@myarray[0],@a,SizeOf(a)); Test(myarray); end; |
PS: APIs bekommen einen Pointer und eine Länge, ein Array of XXX hat direkt beides! Du mixt beides was eben ein Fehler wäre.
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 26.08.08 21:41
Moin!
uall@ogc hat folgendes geschrieben: | Dann hast du aber net ausfühlrich getestet. |
Ich habe getestet, ob die Adresse des records in der Funktion ankommt.  Das tut sie, allerdings leider... uall@ogc hat folgendes geschrieben: | Ein "var x: array of byte" in einer Funktion sind in wirlichkeit zwei Parameter, @x und High(x).
Bei deiner Konvertierung geht zweites verloren -> length und high funktionieren nicht mehr (und auch SetLength). |
...verwirft meine Version die implizite Länge des Datenblocks.  Du hast Recht.
uall@ogc hat folgendes geschrieben: | Ob nun c++ oder Delphi hintersteckt ist egal, Delphi kann mit dem Array weiterarbeiten und es auch wieder verändern (SetLength). |
Habe ich nicht bezweifelt, es kommt eben darauf an, was an Code in dieser ominösen Funktion steckt und ob da die (implizite) Blocklänge übergeben/verwendet wird.
uall@ogc hat folgendes geschrieben: | APIs bekommen einen Pointer und eine Länge, ein Array of XXX hat direkt beides! Du mixt beides was eben ein Fehler wäre. |
Yip, verstanden. Danke für die Nachhilfe.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
|