AGB  ·  Datenschutz  ·  Impressum  







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

C-Funktion mit Pointern in Delphi nachbilden

Ein Thema von oXmoX · begonnen am 1. Jul 2005 · letzter Beitrag vom 4. Jul 2005
Antwort Antwort
oXmoX

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

C-Funktion mit Pointern in Delphi nachbilden

  Alt 1. Jul 2005, 15:32
Hi!

Die folgende C-Funktion möchte ich äquivalent in Delphi abbilden:

Code:
CV_INLINE void cvmSet( CvMat* mat, int i, int j, double val )
{
    ((double*)(mat->data.ptr + (size_t)mat->step*i))[j] = (double)val;
}
CvMat ist eine Matrix-Struktur (siehe unten), dessen Elemente mit der Funktion einzeln belegt werden sollen. i ist die Zeile, j die Spalte und val der einzutragende Wert.

Hier mein Versuch:

Code:
procedure cvmSet(var mat: P_CvMat; i: Integer; j: Integer; val: Double);
var
  PTmpDouble: PDouble;
begin
  PTmpDouble := PDouble(PChar(mat.data.ptr) + mat.step * i);
  Inc(PTmpDouble, j);
  PTmpDouble^ := val;
end;
Die CvMat-Struktur habe ich durch die Hilfe von NicoDE in diesem Topic ja schon umgesetzt bekommen. Vielen Dank nochmal dafür!

Code:
type
  P_CvMat = ^CvMat;
  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;
Das Step steht für die Breite einer Martixzeile in Bytes. ptr zeigt auf den Inhalt.

Mein Problem besteht nun darin, dass ich die Elemente einer 3x3-Matrix mit Werten belege und dann wieder auslese, wobei sich die Werte komplett verändert haben.

Irgendeine Idee?

Gruß,
oXmoX
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#2

Re: C-Funktion mit Pointern in Delphi nachbilden

  Alt 1. Jul 2005, 15:55
Spontanübersetzung (ohne Delphi, Syntaxfehler möglich)
Delphi-Quellcode:
procedure cvmSet(mat: P_CvMat; i, j: Integer; val: Double); {inline;}
type
  PDoubleArray = ^TDoubleArray;
  TDoubleArray = array [Word] of Double;
begin
  PDoubleArray(Cardinal(mat.data.ptr) + Cardinal(mat.step) * i)[j] := val;
end;
mat->data.ptr ist ein Zeiger auf Elemente der Größe 1, dadurch wird für die Addition Faktor 1 verwendet (also ignoriert ).
-> in Delphi können Pointer so nicht addiert werden, deswegen der Cast auf Cardinal

(size_t)mat->step*i step wird auf einen vorzeichenlosen Typen gecastet (hart, old-style) und mit i multipliziert (warum i nicht gecastet wird weiß nicht )
-> das gleiche auch in Delphi Language

((double* )(...))[j] das ganze wird auf einen Zeiger auf Doubles gecastet und mit dem Array-Operator auf dem j-te Element zugegriffen
-> in Delphi kann der Array-Operator so nicht verwendet werden (es gibt keinen ); deswegen wird ein Hilfstyp definiert und verwendet

Gruß Nico

ps: kommt also auf etwa das gleiche raus wie bei dir (bsi auf 'var' und die Zwischenschritte) - bleibt die Frage nach dem Problem...
  Mit Zitat antworten Zitat
oXmoX

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

Re: C-Funktion mit Pointern in Delphi nachbilden

  Alt 1. Jul 2005, 16:05
Hmmm hab deinen Code grad getestet und er liefert die selben Zahlen wie meiner ...auch wenn's bei dir natürlich geschickter aussieht
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#4

Re: C-Funktion mit Pointern in Delphi nachbilden

  Alt 1. Jul 2005, 16:10
Tcha, die Struktur funktioniert aber soweit (oder fehlen noch Fixes für die Alignments der Original-C-Struktur...)?
  Mit Zitat antworten Zitat
oXmoX

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

Re: C-Funktion mit Pointern in Delphi nachbilden

  Alt 1. Jul 2005, 16:20
Zitat von NicoDE:
Tcha, die Struktur funktioniert aber soweit (oder fehlen noch Fixes für die Alignments der Original-C-Struktur...)?
Alignments der Original-C-Struktur??? Was heißt das?

Ich bin bisher noch nicht dazu gekommen, deinen record zu testen. Das wollte ich eigentlich hiermit tun.
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#6

Re: C-Funktion mit Pointern in Delphi nachbilden

  Alt 1. Jul 2005, 16:26
Zitat von oXmoX:
Alignments der Original-C-Struktur?
Delphi-Quellcode:
TFoo = record
  Bar: Byte;
//___: Byte; <- Alignment
  Alc: Word;
end;
Delphi-Quellcode:
TFoo = packed record
  Bar: Byte;
  Alc: Word;
end;
Zitat von oXmoX:
Ich bin bisher noch nicht dazu gekommen, deinen record zu testen. Das wollte ich eigentlich hiermit tun.
Verstehe.
Von hier aus schwer zu sagen, ob ein logischer Fehler vorliegt, oder Strukturen nicht korrekt deklariert sind -> debuggen könnte helfen (je nach Möglichkeit)
  Mit Zitat antworten Zitat
oXmoX

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

Re: C-Funktion mit Pointern in Delphi nachbilden

  Alt 1. Jul 2005, 17:46
Ok, ich komme nicht weiter

Darum hier nochmal mein Code in größerer Ausführlichkeit:

Code:
unit CxCore;

interface

const
  CV_32FC1         = 4;
  CV_64FC1         = 5;

  CV_MAT_TYPE_MASK = 31;

type
  PDoubleArray = ^TDoubleArray;
  TDoubleArray = array [Word] of Double;

  PSingleArray = ^TSingleArray;
  TSingleArray = array [Word] of Single;

  P_CvMat = ^CvMat;
  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;

function cvCreateMat(rows: Integer;
                     cols: Integer;
                     type_: Integer): P_CvMat; cdecl;

function cvmGet(const mat: P_CvMat;
                row: Integer;
                col: Integer): Double; cdecl;
procedure cvmSet(mat: P_CvMat;
                 row: Integer;
                 col: Integer;
                 value: Double); cdecl;

function CV_MAT_TYPE(flags: Cardinal): Cardinal;


implementation

function cvCreateMat(rows: Integer;
                     cols: Integer;
                     type_: Integer): P_CvMat; external 'cxcore096.dll';

function cvmGet(const mat: P_CvMat; row: Integer; col: Integer): Double;
//    external 'cxcore096.dll';
var
  type_:     Integer;
begin
  type_ := CV_MAT_TYPE(mat.type_);
  assert((row < mat.rows) and (col < mat.cols));

  if(type_ = CV_32FC1) then
    Result :=
        PSingleArray(Cardinal(mat.data.ptr) + Cardinal(mat.step) * row)[col]
  else
  begin
    assert(type_ = CV_64FC1);
    Result :=
        PDoubleArray(Cardinal(mat.data.ptr) + Cardinal(mat.step) * row)[col];
  end;
end;

procedure cvmSet(mat: P_CvMat; row: Integer; col: Integer; value: Double);
//    external 'cxcore096.dll';
var
  type_:     Integer;
begin
  type_ := CV_MAT_TYPE(mat.type_);
  assert((row < mat.rows) and (col < mat.cols));

  if(type_ = CV_32FC1) then
    PSingleArray(Cardinal(mat.data.ptr) + Cardinal(mat.step) * row)[col] :=
        value
  else
  begin
    assert(type_ = CV_64FC1);
    PDoubleArray(Cardinal(mat.data.ptr) + Cardinal(mat.step) * row)[col] :=
        value;
  end;
end;

// #define CV_MAT_TYPE(flags)     ((flags) & CV_MAT_TYPE_MASK)
function CV_MAT_TYPE(flags: Cardinal): Cardinal;
begin
  Result := flags and CV_MAT_TYPE_MASK;
end;

end.
Die in der Unit verwendete dll gibt es im Anhang. Sie ist Teil der Open-Source-Bibliothek OpenCV (Beta 4). Sollte das mit der dll alleine nicht funktionieren (aufgrund fehlender Abhängigkeiten etc.), dann lässt sich wohl eine komplette Installation der OpenCV Bibliothek nicht vermeiden (kommt aber mit einer einfachen Setup-Datei). Sollte jemand diesen Aufwand tatsächlich treiben: DANKE dafür.

Die Werte für die Konstanten und die Getter und Setter-Funktion habe ich übrigens aus diesem C-Header-File übernommen.

Jetzt die Test-Unit:

Code:
unit TestMatrix;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, CxCore;

type
  TForm1 = class(TForm)
    ButtonTest64: TButton;
    ButtonTest32: TButton;
    procedure ButtonTest64Click(Sender: TObject);
    procedure ButtonTest32Click(Sender: TObject);
  private
    procedure TestMat(Mat: P_CvMat);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ButtonTest64Click(Sender: TObject);
var
  Mat:     P_CvMat;
begin
  Mat := cvCreateMat(3, 3, CV_64FC1);
  Self.TestMat(Mat);
end;

procedure TForm1.ButtonTest32Click(Sender: TObject);
var
  Mat:     P_CvMat;
begin
  Mat := cvCreateMat(3, 3, CV_32FC1);
  Self.TestMat(Mat);
end;

procedure TForm1.TestMat(Mat: P_CvMat);
var
  Row, Col: Integer;
  Val:     Integer;
begin
  // Matrixwerte belegen
  Val := 0;
  for Row := 0 to 2 do
    for Col := 0 to 2 do
    begin
      cvmSet(Mat, Row, Col, Val);
      Inc(Val);
    end;

  // Matrixwerte auslesen
  for Row := 0 to 2 do
    for Col := 0 to 2 do
    begin
      ShowMessage(FloatToStr(cvmGet(Mat, Row, Col)));
    end;
end;

end.
Bei mir funktioniert der Test nur mit den 32-Bit-Matrizen, nicht aber mit den 64-Bit-Matrizen ...kommen dann beim Auslesen falsche Werte heraus.

Also ...wo ist der Fehler?
Angehängte Dateien
Dateityp: dll cxcore096_204.dll (1.008,1 KB, 2x aufgerufen)
  Mit Zitat antworten Zitat
oXmoX

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

Re: C-Funktion mit Pointern in Delphi nachbilden

  Alt 3. Jul 2005, 13:08
Alles klar! Hab meinen Fehler grad gefunden. Das angegebene C-Header-File ist offensichtlich veraltet, so dass die Konstanten nicht mehr stimmen:

Code:
const
  CV_32FC1         = 4;
  CV_64FC1         = 5;
ist jetzt

Code:
const
  CV_32FC1         = 5;
  CV_64FC1         = 6;
...und schon funktioniert alles reibungslos.

Der variable Record von NicoDE scheint also auch in Ordnung zu sein.
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#9

Re: C-Funktion mit Pointern in Delphi nachbilden

  Alt 4. Jul 2005, 11:01
Soviel zum Thema "Fehler die keiner braucht"
Viel Erfolg mit der weiteren Übersetzung...
  Mit Zitat antworten Zitat
Antwort Antwort


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 21:50 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