Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Delphi-Equivalent zur C-union (https://www.delphipraxis.net/48173-delphi-equivalent-zur-c-union.html)

oXmoX 21. Jun 2005 17:51


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:
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;
in Delphi würde ich schonmal so anfangen:

Code:
CvMat = record
  type_:   Integer;
  step:    Integer;
  refcount: PInteger;

  // ...und wie gehts weiter?

  rows:    Integer;
  cols:    Integer;
end;
Das Delphi-Equivalent für union ist angeblich ein variabler Record. Davon hab ich aber

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

DerDan 21. Jun 2005 18:06

Re: Delphi-Equivalent zur C-union
 
// ...und wie gehts weiter?
// ...und so gehts weiter ->

Delphi-Quellcode:
case integer of
0  : (Ptr : PUCHAR);
1  : (s  : Pshort);
2  : (...);
3  : (...);
end;
mfg der Dan

sniper_w 21. Jun 2005 18:08

Re: Delphi-Equivalent zur C-union
 
Delphi-Quellcode:
type
 myPoint=record
 case (integer) of
 1:(P:array[0..1]of single);
 2:(x,y : single);
 end;
Jetzt kannst du es entweder so:
Delphi-Quellcode:
 variable.e[0] := 44.3;
oder so:
Delphi-Quellcode:
 variable.x := 44.3;
ansprechen.

oXmoX 21. Jun 2005 18:34

Re: Delphi-Equivalent zur C-union
 
Alles klar ...vielen Dank an euch!

oXmoX 21. Jun 2005 18:51

Re: Delphi-Equivalent zur C-union
 
Hmmm ...ich bekomme es immer noch nicht so ganz hin.

Das hier ...

Code:
  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;
funktioniert jedenfalls nicht so direkt.

...und das hier:

Code:
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;
kompiliert zwar. Aber ich bin mir nicht so ganz sicher ob ich alles richtig gemcht habe.

NicoDE 21. Jun 2005 18:59

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:
(** 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;
ps: keine Ursache, hab's gerade nochmal vereinfacht (der Rest war Routine :))

oXmoX 21. Jun 2005 19:11

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!!!

Zerolith 22. Jun 2005 07:57

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!

NicoDE 22. Jun 2005 10:36

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:
//...
    union
    {
        long   foo;
        char   bar;
    };
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.

In Delphi Language nennt man dies den 'varianten Teil einer Struktur'; und so sieht das ganze so aus:
Delphi-Quellcode:
//...
  case Integer of
    0: (
      foo: Longint;
    );
    1: (
      bar: AnsiChar;
    );
{ end; }
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.

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:
//...
    union
    {
        long   foo;
        char   bar;
    };
    int alc;
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:
Delphi-Quellcode:
//...
  case Integer of
    1: (
      bar: AnsiChar;
    );
    0: (
      foo: Longint;
{ end; }
      alc: Integer;
    );
oder anders formatiert:
Delphi-Quellcode:
//...
  case Integer of
    1: (bar: AnsiChar);
    0: (foo: Longint;
  alc: Integer);
Nun haben wir also einen Trick gefunden, um Strukturmitglieder nach einem varianten Teil zu deklarieren.


Dies kann natürlich wieder ein varianter Teil sein, also in der oben gestellten Frage:
Delphi-Quellcode:
//...
  case Integer of
    0: (
      rows : Integer;
    );
    1: (
      height: Integer;
{ end; }
      case Integer of
        0: (
          cols : Integer;
        );
        1: (
          width : Integer;
        );
    );
oder anders formatiert:
Delphi-Quellcode:
//...
  case Integer of
    0: (rows : Integer);
    1: (height: Integer;
  case Integer of
    0: (cols : Integer);
    1: (width : Integer))
  end;
(das Semikolon fehlt nach dem letzten Teil eines Blocks - Geschmacksfrage, aber gültiges Pascal)


Kommen wir am Ende zu benannten C-Unions:
Code:
//...
    union
    {
        long   foo;
        char   bar;
    } dat;
Die Variablen werden nun mit dat.foo und dat.bar angesprochen. Das entspricht der Funktionalität eines Delphi-record.
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:
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;
oder anders formatiert:
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;

NicoDE 22. Jun 2005 10:53

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:
type
  TBar = record
    Foo: TFoo;
    case Integer of
      0: (Int: Integer);
      1: (Ptr: Pointer);
  end;
Foo ist also eine Aufzählung welche angibt, ob in dem direkt folgenden varianten Teil in Integer oder ein Pointer steht.
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:
type
  TBar = record
    Foo: TFoo;
    case TFoo of
      fooInt: (Int: Integer);
      fooPtr: (Ptr: Pointer);
  end;
Da Foo direkt vor dem varianten Teil steht, können wir noch einen Schritt weiter gehen:
Delphi-Quellcode:
type
  TBar = record
    case Foo: TFoo of
      fooInt: (Int: Integer);
      fooPtr: (Ptr: Pointer);
  end;
Foo wird also gleichzeitig deklariert und als Aufzählungstyp für den varianten Teil verwendet.

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 14:33 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz