AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi C++ DLL - Headerkovertierung und Funktionsaufruf
Thema durchsuchen
Ansicht
Themen-Optionen

C++ DLL - Headerkovertierung und Funktionsaufruf

Ein Thema von MatuAC · begonnen am 6. Jun 2011 · letzter Beitrag vom 7. Jun 2011
Antwort Antwort
MatuAC

Registriert seit: 26. Sep 2007
5 Beiträge
 
#1

C++ DLL - Headerkovertierung und Funktionsaufruf

  Alt 6. Jun 2011, 15:04
Delphi-Version: 7
Hallo zusammen,

ich kämpfe im Moment mit einer C++-DLL für die Abfrage einer Kamera, die ich aus Delphi heraus aufrufen möchte. Prinzipiell funktioniert alles, nur bekomme ich als Bilddaten immer nur die ersten 5 Zeichen. Eine Beispiel-EXE, die die gleiche DLL verwendet, kann jedoch problemlos das gesamte Bild anzeigen.

Hier zunächst einmal ein Auszug aus der C++-Header-Datei sowie ein kleines Beispiel in C++:
Code:
#define DUALISPIDK_API __declspec(dllimport)

typedef struct t_O2dResultObject {
    int iModelId;          
    int iPositionX;        
    int iPositionY;        
    float fRotation;      
    float fMatchQuality;  
} T_O2DRESULTOBJECT, *PT_O2DRESULTOBJECT;

typedef struct t_O2dResult {
    T_BOOL bOverallPass;              
    float fOverallMatchQuality;        
    int iNrOfObjectsFound;            
   int iObjectsFoundListSize;         
    PT_O2DRESULTOBJECT objectsFoundList;  
    int iImageSize;                    
    char *image;                      
} T_O2DRESULT, *PT_O2DRESULT;

DUALISPIDK_API int O2dTriggerWithResult (unsigned int iConnectionID, PT_O2DRESULT decodingResult);

------------------------------------------------------------

void demo_O2dTriggerWithResults(unsigned int con_id, const char *filename)
{
    #define maxNumberOfObjects 5
    #define maxImageSize 308278  /* Number of bytes of a Windows Bitmap with 640x 480 pixel, 8 bit */
    int i, retval;
    FILE *fp;
    T_O2DRESULT result;
    T_O2DRESULTOBJECT detail[maxNumberOfObjects];
   
    result.iObjectsFoundListSize = maxNumberOfObjects;
    result.objectsFoundList = detail;
    result.image = (char *)malloc(maxImageSize);
    result.iImageSize = maxImageSize;
    retval = O2dTriggerWithResult(con_id, &result);
    log_retval("O2dTriggerWithResult() returns %d\n", retval);
    printf("bOverallPass         = %d\n", result.bOverallPass);
    printf("fOverallMatchQuality = %6.2f\n", result.fOverallMatchQuality);
    printf("iNrOfObjectsFound    = %d\n", result.iNrOfObjectsFound);
    printf("iObjectsFoundListSize = %d\n", result.iObjectsFoundListSize);
    printf("iImageSize           = %d\n", result.iImageSize);
   
    for (i = 0; i < result.iObjectsFoundListSize; i++)
    {
        printf("Object #%d, iModelId     = %d\n", i, detail[i].iModelId);
        printf("Object #%d, iPositionX   = %d\n", i, detail[i].iPositionX);
        printf("Object #%d, iPositionY   = %d\n", i, detail[i].iPositionY);
        printf("Object #%d, fRotation    = %6.2f\n", i, detail[i].fRotation);
        printf("Object #%d, fMatchQuality = %6.2f\n", i, detail[i].fMatchQuality);
    }
    fp = fopen(filename, "wb");
    fwrite(result.image, 1, result.iImageSize, fp);
    fclose(fp);
   
    free(result.image);
}
Ich habe das ganze wie folgt in Delphi gelöst (dynamische Einbindung der Funktionen lasse ich hier jetzt weg und schreibe nur die entsprechende Funktionsdefinition):
Delphi-Quellcode:
type
  t_O2dResultObject = record
    iModelId: Integer;
    iPositionX: Integer;
    iPositionY: Integer;
    fRotation: Single;
    fMatchQuality: Single;
  end;
  Pt_O2dResultObject = ^t_O2dResultObject;
  t_O2dResult = record
    bOverallPass: T_BOOL;
    fOverallMatchQuality: Single;
    iNrOfObjectsFound: Integer;
    iObjectsFoundListSize: Integer;
    objectsFoundList: PT_O2DRESULTOBJECT;
    iImageSize: Integer;
    image: PChar;
  end;

var
  O2dGetLastResult: function(iConnectionID: DWord; var decodingResult: T_O2DRESULT): integer cdecl;

------------------------------------------------------------

procedure TForm1.Demo;
var
   res: Integer;
   O2dResult: T_O2dResult;
   O2DRESULTOBJECT: Pt_O2DRESULTOBJECT;
begin
   GetMem(O2DResultObject,SizeOf(T_O2DResultObject));
   O2DResult.iObjectsFoundListSize := 1;
   O2DResult.objectsFoundList := O2DResultObject;
   O2DResult.iImageSize := 308278;
   GetMem(O2DResult.image,SizeOf(Char)*308278);
   res := O2DTriggerWithResult(Cam1_ConID,O2DResult);
Da ich das Bild nicht in eine Datei speichern, sondern anders weiter verarbeiten möchte, entfällt hier bei mir der Teil mit dem Speichern in einer Datei.
Aber wie bereits geschrieben, O2DResult.image enthält nach dem Funktionsaufruf zum Abrufen des Bildes nur ganze fünf Zeichen - diese sind aber zumindest korrekt

Was mache ich falsch??

Hoffe, mir kann hier geholfen werden...

Gruß,
Matu
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: C++ DLL - Headerkovertierung und Funktionsaufruf

  Alt 6. Jun 2011, 15:19
AFAIK sind C-Strukturen in Delphi immer packed records.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
MatuAC

Registriert seit: 26. Sep 2007
5 Beiträge
 
#3

AW: C++ DLL - Headerkovertierung und Funktionsaufruf

  Alt 6. Jun 2011, 15:32
Guter Hinweis - macht leider aber keinen Unterschied, ob ich es als packed record oder record deklariere...
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: C++ DLL - Headerkovertierung und Funktionsaufruf

  Alt 6. Jun 2011, 17:14
Ich habe es nun selbst versucht und dabei ist das hier heruasgekommen. Da ich aber nicht sonderlich viel Ahnung von C/C++ habe, kann das auch völliger Quatsch sein, probier es halt einmal.
Delphi-Quellcode:
type
  P_O2DRESULTOBJECT = ^T_O2DRESULTOBJECT;
  T_O2DRESULTOBJECT = packed record
    iModelId: integer;
    iPositionX: integer;
    iPositionY: integer;
    fRotation: single;
    fMatchQuality: single;
  end;

  P_O2DRESULT = ^T_O2DRESULT;
  T_O2DRESULT = packed record
    bOverallPass: T_BOOL;
    fOverallMatchQuality: single;
    iNrOfObjectsFound: integer;
    iObjectsFoundListSize: integer;
    objectsFoundList: P_O2DRESULTOBJECT;
    iImageSize: integer;
    image: PByte;
  end;
  
var
  O2dGetLastResult: function(iConnectionID: DWord; var decodingResult: T_O2DRESULT): integer; cdecl;
  
 procedure demo_O2dTriggerWithResults(con_id: Cardinal; const filename: string);
 const
   maxNumberOfObjects = 5;
   maxImageSize = 308278;
 var
   i, retval: integer;
   _result: T_O2DRESULT;
   detail: array[0..maxNumberOfObjects - 1] of T_O2DRESULTOBJECT;
   image: PByte;
 begin
    _result.iObjectsFoundListSize := maxNumberOfObjects;
    _result.objectsFoundList := @detail[Low(Detail)];
    image := AllocMem(maxImageSize);
    try
      _result.image := image;
      _result.iImageSize := maxImageSize;
      retval := O2dGetLastResult(con_id, _result);
      for i := 0 to result.iObjectsFoundListSize - 1 do
        (* irgendwas machen *)
    finally
      FreeMem(image);
    end;
 end;
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
MatuAC

Registriert seit: 26. Sep 2007
5 Beiträge
 
#5

AW: C++ DLL - Headerkovertierung und Funktionsaufruf

  Alt 7. Jun 2011, 08:05
Nochmals vielen Dank für die Hilfe!!

Ich habe jetzt meinen Fehler gefunden - es lag nicht an den DLL-Aufrufen, das war wohl doch schon alles korrekt. Vielmehr hatte ich einen Fehler bei der weiteren Verarbeitung gemacht...

Da ich den ausgelesenen Bildinhalt in einem String haben wollte, hatte ich einfach folgende Zuweisung gemacht:
tmpstr := _result.image; Hat so erstmal ohne Fehler geklappt, da ich ja als _result.image den Typ PChar verwendet hatte.
Allerdings scheint hört Delphi beim umkopieren beim ersten Byte mit dem Wert "0" auf...
Ich mache es jetzt so:
copymemory(@tmpstr[1],_result.image,_result.iImageSize); und damit klappt es jetzt Es macht dann auch keinen Unterschied, ob ich PChar oder PByte verwende.

Gruß,
MatuAC
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: C++ DLL - Headerkovertierung und Funktionsaufruf

  Alt 7. Jun 2011, 08:18
Naja, PChar ist ja so definiert, dass der enthaltene String mit dem ersten 0-Zeichen endet (deshalb heißt es ja "nullterminierter String"), darum war ich auf PByte umgestiegen (außerdem macht C/C++ IIRC keinen Unterschied zwischen Byte und Char, der Datentyp ist in beiden Fällen char).

[edit] Aus diesem Grund ist Deine Multiplikation mit SizeOf(Char) auch eigentlich falsch, da Du auf einem Unicode-Delphi doppelt so viel Speicher anfordern würdest wie tatsächlich benötigt werden. [/edit]
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
MatuAC

Registriert seit: 26. Sep 2007
5 Beiträge
 
#7

AW: C++ DLL - Headerkovertierung und Funktionsaufruf

  Alt 7. Jun 2011, 08:26
Grade wegen "nullterminierter String" war ich dann auch noch auf den Fehler gekommen - leider komme ich nur noch selten dazu, in Delphi programmieren zu können, deshalb hatte ich ersteinmal nicht mehr daran gedacht

Ich benutze noch das "Ur-Alt" Delphi 7... Vielleicht ist es bei neueren Delphi Versionen anders, aber bei mir bekomme ich bei SizeOf(Char) "1" zurück, somit war es hier auch kein Unterschied...
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: C++ DLL - Headerkovertierung und Funktionsaufruf

  Alt 7. Jun 2011, 08:29
Sicher, bis einschließlich Delphi 2007 ist ein Char auch ein AnsiChar -> 1 Byte, ab Delphi 2009 ist das allerdings ein WideChar -> 2 Byte.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  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 06:10 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