AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Delphi-Equivalent zur C-union

Ein Thema von oXmoX · begonnen am 21. Jun 2005 · letzter Beitrag vom 22. Jun 2005
Antwort Antwort
Seite 1 von 2  1 2      
oXmoX

Registriert seit: 8. Jun 2005
85 Beiträge
 
#1

Delphi-Equivalent zur C-union

  Alt 21. Jun 2005, 17:51
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
  Mit Zitat antworten Zitat
DerDan

Registriert seit: 15. Nov 2004
Ort: Donaueschingen
251 Beiträge
 
Delphi XE3 Professional
 
#2

Re: Delphi-Equivalent zur C-union

  Alt 21. Jun 2005, 18:06
// ...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
nichts ist so schön wie man es sich vorstellt
  Mit Zitat antworten Zitat
Benutzerbild von sniper_w
sniper_w

Registriert seit: 11. Dez 2004
Ort: Wien, Österriech
893 Beiträge
 
Delphi 6 Enterprise
 
#3

Re: Delphi-Equivalent zur C-union

  Alt 21. Jun 2005, 18:08
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:
 variable.e[0] := 44.3; oder so:
 variable.x := 44.3; ansprechen.
Katura Haris
Es (ein gutes Wort) ist wie ein guter Baum, dessen Wurzel fest ist und dessen Zweige in den Himmel reichen.
  Mit Zitat antworten Zitat
oXmoX

Registriert seit: 8. Jun 2005
85 Beiträge
 
#4

Re: Delphi-Equivalent zur C-union

  Alt 21. Jun 2005, 18:34
Alles klar ...vielen Dank an euch!
  Mit Zitat antworten Zitat
oXmoX

Registriert seit: 8. Jun 2005
85 Beiträge
 
#5

Re: Delphi-Equivalent zur C-union

  Alt 21. Jun 2005, 18:51
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.
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#6

Re: Delphi-Equivalent zur C-union

  Alt 21. Jun 2005, 18:59
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 )
  Mit Zitat antworten Zitat
oXmoX

Registriert seit: 8. Jun 2005
85 Beiträge
 
#7

Re: Delphi-Equivalent zur C-union

  Alt 21. Jun 2005, 19:11
Hey NicoDE,

da hast du dir aber echt Mühe gegeben.
Ich werd das morgen mal ausprobieren.

Vielen Dank!!!
  Mit Zitat antworten Zitat
Zerolith

Registriert seit: 12. Mär 2003
Ort: Kempten
188 Beiträge
 
Delphi 6 Enterprise
 
#8

Re: Delphi-Equivalent zur C-union

  Alt 22. Jun 2005, 07:57
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!
Daniel
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#9

Re: Delphi-Equivalent zur C-union

  Alt 22. Jun 2005, 10:36
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;
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#10

Re: Delphi-Equivalent zur C-union

  Alt 22. Jun 2005, 10:53
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.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:08 Uhr.
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