![]() |
Delphi-Equivalent zur C-union
Hi,
hoffe mir kann jemand mit etwas C bzw. C++ Erfahrung mit meinem Problem helfen. Ich verwende eine externe C++ Bibliothek in meinem Delphi-Code. Dazu "baue" ich einfach alle für die Parameterübergabe benötigten Typen in Delphi nach. Das funktioniert natürlich auch mit records (in C sind das dann structures). Mit der folgenden structure habe ich allerdings so meine Probleme beim "nachbauen":
Code:
in Delphi würde ich schonmal so anfangen:
typedef struct CvMat
{ int type; int step; /* for internal use only */ int* refcount; union { uchar* ptr; short* s; int* i; float* fl; double* db; } data; #ifdef __cplusplus union { int rows; int height; }; union { int cols; int width; }; #else int rows; int cols; #endif } CvMat;
Code:
Das Delphi-Equivalent für union ist angeblich ein variabler Record. Davon hab ich aber
CvMat = record
type_: Integer; step: Integer; refcount: PInteger; // ...und wie gehts weiter? rows: Integer; cols: Integer; end; keine Ahnung. Ebensowenig, wie von den Preprocessor-Anweisungen im C-Code ...muss ich die etwa auch "nachbauen"? Bin für jeden Hinweis dankbar! Gruß, oXmoX |
Re: Delphi-Equivalent zur C-union
// ...und wie gehts weiter?
// ...und so gehts weiter ->
Delphi-Quellcode:
mfg der Dan
case integer of
0 : (Ptr : PUCHAR); 1 : (s : Pshort); 2 : (...); 3 : (...); end; |
Re: Delphi-Equivalent zur C-union
Delphi-Quellcode:
Jetzt kannst du es entweder so:
type
myPoint=record case (integer) of 1:(P:array[0..1]of single); 2:(x,y : single); end;
Delphi-Quellcode:
oder so:
variable.e[0] := 44.3;
Delphi-Quellcode:
ansprechen.
variable.x := 44.3;
|
Re: Delphi-Equivalent zur C-union
Alles klar ...vielen Dank an euch!
|
Re: Delphi-Equivalent zur C-union
Hmmm ...ich bekomme es immer noch nicht so ganz hin.
Das hier ...
Code:
funktioniert jedenfalls nicht so direkt.
CvMat = record
type_: Integer; step: Integer; // for internal use only refcount: PInteger; case Integer of 0: (ptr: PUCHAR); 1: (s: PShortInt); 2: (i: Integer); 3: (fl: Single); 4: (db: Double); end; rows: Integer; cols: Integer; end; ...und das hier:
Code:
kompiliert zwar. Aber ich bin mir nicht so ganz sicher ob ich alles richtig gemcht habe.
cvMatInner = record
case Integer of 0: (ptr: PUCHAR); 1: (s: PShortInt); 2: (i: Integer); 3: (fl: Single); 4: (db: Double); end; CvMat = record type_: Integer; step: Integer; // for internal use only refcount: PInteger; inner: cvMatInner; rows: Integer; cols: Integer; end; |
Re: Delphi-Equivalent zur C-union
Das lässt sich nur mit vielen Tricks übersetzen.
(wer auch immer unbenannte unions benutzt, gehört...)
Delphi-Quellcode:
ps: keine Ursache, hab's gerade nochmal vereinfacht (der Rest war Routine :))
(** Unnamed unions are evil stuff.
typedef struct CvMat { int type; int step; int* refcount; union { uchar* ptr; short* s; int* i; float* fl; double* db; } data; union { int rows; int height; }; union { int cols; int width; }; } CvMat; **) type CvMat = record type_ : Integer; step : Integer; (* for internal use only *) refcount : PInteger; data : record case Integer of 0: (ptr : PByte); 1: (s : PSmallInt); 2: (i : PInteger); 3: (fl : PSingle); 4: (db : PDouble) end; case Integer of 0: (rows : Integer); 1: (height: Integer; case Integer of 0: (cols : Integer); 1: (width : Integer)) end; // unit testing procedure TForm1.FormCreate(Sender: TObject); function FielsOffset(const Struct; const Field): string; begin Result := IntToHex(Cardinal(Addr(Field)) - Cardinal(Addr(Struct)), 8); end; var Foo: CvMat; Txt: string; begin Txt := 'type_ ' + FielsOffset(Foo, Foo.type_ ) + #13#10 + // 00000000 'step ' + FielsOffset(Foo, Foo.step ) + #13#10 + // 00000004 'refcount ' + FielsOffset(Foo, Foo.refcount) + #13#10 + // 00000008 'data ' + FielsOffset(Foo, Foo.data ) + #13#10 + // 0000000C ' ptr ' + FielsOffset(Foo, Foo.data.ptr) + #13#10 + // 0000000C ' s ' + FielsOffset(Foo, Foo.data.s ) + #13#10 + // 0000000C ' i ' + FielsOffset(Foo, Foo.data.i ) + #13#10 + // 0000000C ' fl ' + FielsOffset(Foo, Foo.data.fl ) + #13#10 + // 0000000C ' db ' + FielsOffset(Foo, Foo.data.db ) + #13#10 + // 0000000C 'rows ' + FielsOffset(Foo, Foo.rows ) + #13#10 + // 00000010 'height ' + FielsOffset(Foo, Foo.height ) + #13#10 + // 00000010 'cols ' + FielsOffset(Foo, Foo.cols ) + #13#10 + // 00000014 'width ' + FielsOffset(Foo, Foo.width ) + #13#10 + // 00000014 '(SizeOf) ' + IntToHex(SizeOf(CvMat), 8); // 00000018 ShowMessage(Txt); end; |
Re: Delphi-Equivalent zur C-union
Hey NicoDE,
da hast du dir aber echt Mühe gegeben. Ich werd das morgen mal ausprobieren. Vielen Dank!!! |
Re: Delphi-Equivalent zur C-union
Sorry, dass ich mich hier so einmische - aber ich blick das nicht. hab mir jetzt 10 minuten den source angeschaut. Aber was ist das? Sowas geht mit Delphi? Was macht es? erklärt es mir bitte!
|
Re: Delphi-Equivalent zur C-union
Ein C-struct entspricht einem Delphi-record; soweit dürfte das klar sein.
Nehmen wir mal die C-Union:
Code:
Unions werden verwendet um die gleiche Variable (Speicheradresse) mit verschiedenen Namen ansprechen zu können. '.foo' und '.bar' sind also an der gleichen Stelle (und eigentlich eine Variable). In der Variable steht entweder ein 'Foo'-Wert oder ein 'Bar'-Wert (die Unterscheidung zwischen den beiden Bedeutungen einer Variable muss irgendwo in der Dokumentation stehen...). Verwendet wird das ganze meist um Speicherplatz zu sparen.
//...
union { long foo; char bar; }; In Delphi Language nennt man dies den 'varianten Teil einer Struktur'; und so sieht das ganze so aus:
Delphi-Quellcode:
Integer als Aufzählungstyp ist frei gewählt. Die einzelnen Varianten der Struktur sind in Delphi-Language deutlicher zu erkennen als in C. Man muss sich nur an das 'case'-Konstrukt in Strukturen gewöhnen.
//...
case Integer of 0: ( foo: Longint; ); 1: ( bar: AnsiChar; ); { end; } Warum ist nun das Ende des varianten Teils der Struktur auskommentiert? Nun, die Delphi Language unterstützt variante Teile nur als letzten Teil einer Struktur. Es können also keine weiteren Variablen folgen! Was soll man dann aber mit folgenden C-Konstrukt anstellen?
Code:
Da in der Delphi-Language keine weiteren Variablen folgen können, müssen wir die folgenden Strukturmitglieder an den größten Teil der varianten Struktur anhängen. Da .foo größer ist als .bar, müssen wir beide vertauschen. Das ganze sieht dann so aus:
//...
union { long foo; char bar; }; int alc;
Delphi-Quellcode:
oder anders formatiert:
//...
case Integer of 1: ( bar: AnsiChar; ); 0: ( foo: Longint; { end; } alc: Integer; );
Delphi-Quellcode:
Nun haben wir also einen Trick gefunden, um Strukturmitglieder nach einem varianten Teil zu deklarieren.
//...
case Integer of 1: (bar: AnsiChar); 0: (foo: Longint; alc: Integer); Dies kann natürlich wieder ein varianter Teil sein, also in der oben gestellten Frage:
Delphi-Quellcode:
oder anders formatiert:
//...
case Integer of 0: ( rows : Integer; ); 1: ( height: Integer; { end; } case Integer of 0: ( cols : Integer; ); 1: ( width : Integer; ); );
Delphi-Quellcode:
(das Semikolon fehlt nach dem letzten Teil eines Blocks - Geschmacksfrage, aber gültiges Pascal)
//...
case Integer of 0: (rows : Integer); 1: (height: Integer; case Integer of 0: (cols : Integer); 1: (width : Integer)) end; Kommen wir am Ende zu benannten C-Unions:
Code:
Die Variablen werden nun mit dat.foo und dat.bar angesprochen. Das entspricht der Funktionalität eines Delphi-record.
//...
union { long foo; char bar; } dat; Also übersetzen wir die benannte Union mit einem inline-record:
Delphi-Quellcode:
//...
dat: record case Integer of 0: ( foo: Longint; ); 1: ( bar: AnsiChar; ); { end; } end; Wenn wir nun unser gewonnenes Wissen bündeln und die Macht mit uns ist, dann können wir den oben gefragten C-Code mit folgendem Übersetzen:
Delphi-Quellcode:
oder anders formatiert:
type
CvMat = record type_: Integer; step: Integer; refcount: PInteger; data: record case Integer of 0: ( ptr: PByte; ); 1: ( s: PSmallInt; ); 2: ( i: PInteger; ); 3: ( fl: PSingle; ); 4: ( db: PDouble; ); { end; } end; case Integer of 0: ( rows: Integer; ); 1: ( height: Integer; { end; } case Integer of 0: ( cols: Integer; ); 1: ( width: Integer; ); { end; } ); end;
Delphi-Quellcode:
type
CvMat = record type_ : Integer; step : Integer; refcount : PInteger; data : record case Integer of 0: (ptr : PByte); 1: (s : PSmallInt); 2: (i : PInteger); 3: (fl : PSingle); 4: (db : PDouble) end; case Integer of 0: (rows : Integer); 1: (height: Integer; case Integer of 0: (cols : Integer); 1: (width : Integer)) end; |
Re: Delphi-Equivalent zur C-union
Abschliesend noch weitere Hinweise zu varianten Stukturen.
Nemen wir folgende Deklarationen:
Delphi-Quellcode:
type
TFoo = (fooInt, fooPtr);
Delphi-Quellcode:
Foo ist also eine Aufzählung welche angibt, ob in dem direkt folgenden varianten Teil in Integer oder ein Pointer steht.
type
TBar = record Foo: TFoo; case Integer of 0: (Int: Integer); 1: (Ptr: Pointer); end; Da TFoo ein Aufzählungstyp ist (und im semantischen Zusammenhang mit dem varianten Teil) steht, können wir TFoo auch als Aufzählungstyp für den varianten Teil benutzen:
Delphi-Quellcode:
Da Foo direkt vor dem varianten Teil steht, können wir noch einen Schritt weiter gehen:
type
TBar = record Foo: TFoo; case TFoo of fooInt: (Int: Integer); fooPtr: (Ptr: Pointer); end;
Delphi-Quellcode:
Foo wird also gleichzeitig deklariert und als Aufzählungstyp für den varianten Teil verwendet.
type
TBar = record case Foo: TFoo of fooInt: (Int: Integer); fooPtr: (Ptr: Pointer); end; Diese Art der Deklaration dokumentiert die Bedeutung von Foo und des varianten Teils besser als die ursprüngliche Variante. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:29 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 by Thomas Breitkreuz