Autor Beitrag
Sprotti
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26



BeitragVerfasst: Di 26.08.08 13:15 
Hallo,
ich habe mir ein packed record zusammengestellt in dem ich meine Daten schön ordentlich aufliste.


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
TMyRecord = packed record
  bla    : Integer;
  blub   : Byte;
  thing  : array[0..4of Longword;
end;


Dieses record hätte ich jetzt gerne zur Übergabe an folgende function als array of byte.


ausblenden 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
  //aRecord wird mit 0en gefüllt
  ...

  //hier die Stelle wo ich Eure Hilfe brauche
  //???Umwandlung des Records in Array
  //???anArray:=aRecord;
  
  PutGetAByteArray(anArray);

  //hier die Stelle wo ich Eure Hilfe brauche
  //???Umwandlung des Arrays zurück zum Record
  //???aRecord:=anArray;

  //hier sollte bla den Wert $0050 haben
  if bla=$0050 then
    Result:=true;
end;


könnt Ihr mir bitte helfen die Konvertierungen richtig hizukriegen?
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: 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. :nixweiss:

Vielleicht erklärst du mal kurz, was das werden soll, dann ist es leichter, was dazu zu sagen. :idea: ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Sprotti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 26.08.08 15:23 
Titel: Re: Methode braucht Parametertyp
Moin!

user profile iconSprotti 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.

user profile iconSprotti 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. :idea:

user profile iconSprotti 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 26



BeitragVerfasst: Di 26.08.08 15:55 
user profile iconNarses hat folgendes geschrieben:

Zeig doch mal diese Methode, ...


ausblenden Delphi-Quelltext
1:
2:
3:
4:
function TMyClass.PutGetAByteArray(var myarray:array of byte);
begin
  transcryptor.SendReceiveData(myarray);
end;


Von der Zielklasse ist nur die Deklaration vorhanden
ausblenden Delphi-Quelltext
1:
function TTransCrypt.SendReceiveData(var Data:array of byte):Longword;					


Aber ist denn diese Information wirklich notwendig um eine Möglichkeit zu finden ein record in ein array of byte typ zu konvertieren? Die Records die ich nutze enthalten keine dynamischen Elemente. D.h. sie haben immer eine feste Größe und Struktur.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 26.08.08 16:58 
Moin!

user profile iconSprotti hat folgendes geschrieben:
ausblenden 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... :lol:

user profile iconSprotti hat folgendes geschrieben:
Von der Zielklasse ist nur die Deklaration vorhanden
ausblenden 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... :nixweiss:

user profile iconSprotti 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?! :shock: Das kann übel ins Auge gehen, wenn man Speicher überschreibt, der einem nicht gehört. :idea: 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:
ausblenden 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
  //transcryptor.SendReceiveData(myarray);
  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! :mahn: (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...)

user profile iconSprotti 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: 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:

ausblenden 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)); // weiß jetzt selbst net ob zuerst src oder dst kommt
  SendReceiveData(bla);
  
  // jetzt kann bla verändert worden sein, d.h. auch die Größe!
  // deshalb kann es nicht sofort zurückkopiert sein (der Recv Record kann anders aussehen)


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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 26.08.08 20:04 
Moin!

user profile iconuall@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. :zwinker:

user profile iconuall@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? :gruebel: Oder hab ich da was falsch verstanden? :nixweiss: 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).

user profile iconuall@ogc hat folgendes geschrieben:
So sollte es gehen:
ausblenden 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)); // weiß jetzt selbst net ob zuerst src oder dst kommt
  SendReceiveData(bla);
  // jetzt kann bla verändert worden sein, d.h. auch die Größe!
  // deshalb kann es nicht sofort zurückkopiert sein (der Recv Record kann anders aussehen)
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). :nixweiss:

user profile iconuall@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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: 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):

ausblenden 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)); // Narses

  SetLength(myarray, SizeOf(a));
  CopyMemory(@myarray[0],@a,SizeOf(a));
  Test(myarray); // Meins
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 26.08.08 21:41 
Moin!

user profile iconuall@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...
user profile iconuall@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. :shock: Du hast Recht. :oops:

user profile iconuall@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. :?

user profile iconuall@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.