![]() |
Delphi-Version: 7
C++ DLL - Headerkovertierung und Funktionsaufruf
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:
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):
#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); }
Delphi-Quellcode:
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.
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); 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 |
AW: C++ DLL - Headerkovertierung und Funktionsaufruf
AFAIK sind C-Strukturen in Delphi immer packed records.
|
AW: C++ DLL - Headerkovertierung und Funktionsaufruf
Guter Hinweis - macht leider aber keinen Unterschied, ob ich es als packed record oder record deklariere...
|
AW: C++ DLL - Headerkovertierung und Funktionsaufruf
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; |
AW: C++ DLL - Headerkovertierung und Funktionsaufruf
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:
Delphi-Quellcode:
Hat so erstmal ohne Fehler geklappt, da ich ja als _result.image den Typ PChar verwendet hatte.
tmpstr := _result.image;
Allerdings scheint hört Delphi beim umkopieren beim ersten Byte mit dem Wert "0" auf... Ich mache es jetzt so:
Delphi-Quellcode:
und damit klappt es jetzt :) Es macht dann auch keinen Unterschied, ob ich PChar oder PByte verwende.
copymemory(@tmpstr[1],_result.image,_result.iImageSize);
Gruß, MatuAC |
AW: C++ DLL - Headerkovertierung und Funktionsaufruf
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] |
AW: C++ DLL - Headerkovertierung und Funktionsaufruf
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... |
AW: C++ DLL - Headerkovertierung und Funktionsaufruf
Sicher, bis einschließlich Delphi 2007 ist ein Char auch ein AnsiChar -> 1 Byte, ab Delphi 2009 ist das allerdings ein WideChar -> 2 Byte.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:01 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-2025 by Thomas Breitkreuz