![]() |
C++ DLL (Funktion) nach Delphi
Hallo,
ich habe eine Frage zu folgender Deklaration einer Funktion in einer C++ DLL, welche ich ansprechen muss:
Delphi-Quellcode:
Im Delphi würde ich die dann wie folgt deklarieren:
typedef char My_STRING;
Res_DWORD Get_Error_Text ( ERROR_T *error, // in const My_STRING *language, // in My_STRING text[1024] ); // out
Delphi-Quellcode:
Aufruf dann so:
type
PERROR = ^TERROR; TERROR = packed Record Long1 : LongWord; Long2 : LongWord; Byte1 : BYTE; Byte2 : BYTE; Byte3 : BYTE; end; function Get_Error_Text(aError: PERROR; aLanguage: String; out aErrStr: String): LongWord;stdcall;external 'ExterneDLL.dll';
Delphi-Quellcode:
Mein Problem ist, dass in der Errorstruktur ein Fehler ansteigt aber mit meinem Aufruf bekomme ich immer in "ErrStr" nur ein LeerString geliefert. Könnt ihr mir sagen, wo das Problem besteht? ich vermute ein Fehler mit dem Datentyp String, dem Char und dem beschreiben des Parameters "ErrStr" beim Aufruf der DLL.
procedure TForm1.Button1Click(Sender: TObject);
Const ErrLanguage = 'English'; var ErrClass : LongWord; ErrStruct : TERROR; ErrStr : String; begin ErrClass := Get_Error_Text(@ErrStruct, ErrLanguage, ErrStr); ShowMessage(ErrStr); end; |
AW: C++ DLL (Funktion) nach Delphi
Versuch es mal so: (ungertestet)
Delphi-Quellcode:
type
TERROR = packed Record Long1 : LongWord; Long2 : LongWord; Byte1 : BYTE; Byte2 : BYTE; Byte3 : BYTE; end; type ErrorStr = Array[0..1024-1] of AnsiChar; function Get_Error_Text(var aError: TERROR; aLanguage: PAnsiChar; var aErrStr: ErrorStr): LongWord;stdcall;external 'ExterneDLL.dll'; procedure Button1Click; Const ErrLanguage : AnsiString = 'English'; var ErrClass : LongWord; ErrStruct : TERROR; ErrStr : ErrorStr; myErrorstring : String; begin ErrClass := Get_Error_Text(ErrStruct, PansiChar(ErrLanguage), ErrStr); myErrorstring := String(AnsiString(ErrStr)); ShowMessage( myErrorstring); end; |
AW: C++ DLL (Funktion) nach Delphi
Gemanagte Typen ala String, Interfaces oder dynamische Arrays besser niemals als OUT-Parameter deklatieren, sondern nur als VAR.
Und dann ist dieses C++-Char-Array kein Delphi-String, weswegen dein Code nicht funktionieren kann, wenn du inkompatible Typen auf beiden Seiten (DLL und EXE) hast. Wenn das aber deine DLL ist und du unbedingt "Strings" haben willst, dann nimm in Delphi den WideString, denn dieser Typ kapelst den BSTR der OleAuth32.dll, welche du auch im C++ nutzen kannst. ![]() Außerdem, wenn du gemaagte Typen ala String über Modulgrenzen (EXE/DLL) hinweg nutzen willst, dann muß du auch den Speichermanager vom Delphi überall gemeinsam nutzen. ![]() ![]() |
AW: C++ DLL (Funktion) nach Delphi
Die DLL ist leider nicht von mir, deswegen kann ich da nichts ändern. Ich werde den Code von Fritzew morgen mal probieren.
@Himitsu: wie müsste ich es denn auf der Delphi Seite deklarieren, damit es funktioniert? Ich habe leider nur eine Doku in Form einer PDF. |
AW: C++ DLL (Funktion) nach Delphi
Ich möchte bezweifeln das die Struct unter C++ mit 1 Byte alignment definiert wurde.
Was soll also dieses packed Record? gibt es so etwas wie.. in dem C++ code?
Code:
denke nicht.
#pragma pack(push, 1)
Wenn also die Ausrichtung der struct (record) schon nicht stimmt wie soll das andere dann funktionieren. gruss |
AW: C++ DLL (Funktion) nach Delphi
Die Struktur ist so deklariert:
Delphi-Quellcode:
Ich glaube daher schon, dass meine packed record Struktur richtig ist, es steht ja auch ein sinnvoller Wert in die beiden Long-Variablen.
typedef unsigned char My_BYTE;
typedef unsigned long My_DWORD; typedef struct My_ERROR { My_DWORD Long1; My_DWORD Long2; My_BYTE Byte1; My_BYTE Byte2; My_BYTE Byte3; } PPC_BYTE_PACKED My_ERROR_T; |
AW: C++ DLL (Funktion) nach Delphi
Mit der Variante von Fritzew steht schonmal was in dem ErrStr drinne.
Leider sind nicht alle 1024 Zeichen sinnvoll gefüllt, aber ca. 200 steht nur noch "Mist" drin. Wenn ich jetzt die Umwandlung auf ein String mache, bekomme ich eine Zugriffsverletzung (Exception). Man müsste jetzt bestimmt die Länge noch herausbekommen, da nicht immer alle 1024 Zeichen gefüllt sind. |
AW: C++ DLL (Funktion) nach Delphi
Zitat:
Aber gut bin raus ;) ![]() gruss |
AW: C++ DLL (Funktion) nach Delphi
Zitat:
Alternativ kannst du auch den Text vor der Übergabe an die Funktion mit FillChar nullen. Das wird wahrscheinlich auch funktionieren. |
AW: C++ DLL (Funktion) nach Delphi
Zitat:
Delphi-Quellcode:
ein.
fillchar(ErrStr, Sizeof(ErrStr), 0);
Der Einwurf von EWeis ist schon richtig. aber ohne header file ist es schwer zu sagen. (Trotz roter Box abgeschickt) |
AW: C++ DLL (Funktion) nach Delphi
Stimmt, das FillChar hatte gefehlt.
Leider liefert mir die Funktion nicht die Länge zurück, nur ob sie erfolgreich ausgeführt werden konnte. Aber mit dem FillChar geht es jetzt. Danke für die Hilfe. Der Link von EWeiss ist auch sehr gut! |
AW: C++ DLL (Funktion) nach Delphi
Ich habe noch ein Fall den ich euch gerne schildern möchte:
Deklaration in C:
Delphi-Quellcode:
In der Doku für den Befehl "start_func" steht für den Parameter "Name2" folgendes:
typedef unsigned long My_DWORD;
typedef char My_STRING; My_DWORD start_func (const My_STRING *name1, // in const My_STRING *name2, // in ERROR_T *error ); // out Nullzeiger eintragen. In einem C Beispiel, welches ich aber nicht debuggen kann, ist der Aufruf so gemacht:
Delphi-Quellcode:
Ich habe ein fertiges C Programm, welches genau dieses Befehl aufruft, welchen ich nun im Delphi nachprogrammieren möchte.
My_STRING *pname2 = NULL;
ErrClass = start_func((My_STRING *)name1, pname2, &ErrStruct); Das Ergebnis im C Programm ist, dass die Funktion 0 liefert (also kein Fehler). Ich bekomme immer ein Fehler (Result <> 0), also vermute ich ein Fehler bei meiner Parameterübergabe. Gelöst habe ich es so:
Delphi-Quellcode:
Aber egal was ich als zweiten Parameter übergebe (Nil, Leerzeichen etc.) ich bekomme als Result nie eine 0.
function start_func(Name1: PAnsiChar; Name2: PAnsiChar; aError: PERROR): LongWord;stdcall;external DP_DLL;
Aufruf: start_func(PAnsiChar(MyNAME1), Nil, @ErrStruct); Heißt für mich, dass mein Delphi Programm die Funktion anders aufruft wie das C Programm. Habt ihr noch eine Idee? |
AW: C++ DLL (Funktion) nach Delphi
Versuch mal so:
Delphi-Quellcode:
Sollte eigentlich funktionieren
function start_func(const Name1: PAnsiChar; const Name2: PAnsiChar; aError: PERROR): LongWord;stdcall;external DP_DLL;
|
AW: C++ DLL (Funktion) nach Delphi
Das hat geholfen, danke! :thumb:
|
AW: C++ DLL (Funktion) nach Delphi
Hallo,
ich bin mir nicht sicher, ob ich hier nochmal eine Frage zu dem Thema stellen kann oder ob ich ein neuen Thread hätte aufmachen sollen (gebt mir eine Info wenn ich ein neuen Thread aufmachen soll). Folgendes Konstrukt habe ich in C vorliegen:
Delphi-Quellcode:
Dieses Struktur muss ich jetzt nach Delphi umbauen.
#define My_MAX_ADDR 127U
#define My_MAX_NR (My_MAX_ADDR + 1) typedef unsigned char My_BYTE; typedef unsigned short My_WORD; typedef unsigned long My_DWORD; typedef long My_LONG; typedef struct My_DATA_INT_S { My_BYTE value1; My_BYTE no_ram_here_dont_touch[0x00FF]; } PPC_BYTE_PACKED My_DATA_INT_T; typedef struct My_EF_S { My_DATA_INT_T value1[My_MAX_NR]; My_BYTE reserved_b_00[0x8000]; My_DATA_INT_T value2[My_MAX_NR]; My_BYTE reserved_b_01[0x8000]; } PPC_BYTE_PACKED My_EF_T; Mein Vorschlag (bin mir mit den Hex-Offsets hinter den Variablen aber nicht sicher):
Delphi-Quellcode:
Den packed record für "My_EF_T" bekomme ich leider nicht abgebildet.
const
My_MAX_ADDR = 127; My_MAX_NR = (My_MAX_ADDR + 1); type TMy_MASK_DATA_INT = packed record value1 : BYTE; no_ram_here_dont_touch : BYTE; end; Habt ihr eine Idee wie man das umsetzen könnte? So vielleicht?
Delphi-Quellcode:
type
TMy_EF = packed record value1 : array[0..My_MAX_NR] of TMy_MASK_DATA_INT; reserved_b_00 : BYTE; value2 : array[0..My_MAX_NR] of TMy_MASK_DATA_INT; reserved_b_01 : BYTE; end; |
AW: C++ DLL (Funktion) nach Delphi
CArray[ANZAHL] = DelphiArray[VON..BIS] aka DelphiArray[0..ANZAHL-1]
Und C-Arrays sind nicht standardmäßig gepackt. Also vermutlich ohne PACKED und mit passendem {$ALIGN}. ![]() |
AW: C++ DLL (Funktion) nach Delphi
Danke für den Hinweis.
Ist denn die Implementierung von "TMy_EF" sonst korrekt? Ich bin mir wie gesagt nicht sicher wegen der Hex Angabe hinter den Variablen. Es gibt auch solche Konstrukte, welche ich nachbilden muss:
Delphi-Quellcode:
Da sieht das Align anders aus im Delphi oder? Aber die Hex-Angabe verstehe ich aktuell noch nicht.
typedef struct My_INFO_S
{ My_BYTE reserved_b_00[0xF0]; My_BYTE reserved_b_10[0x2FC]; } BYTE_PACKED_ALIGN4 /* PPC_BYTE_PACKED */ My_INFO_T; |
AW: C++ DLL (Funktion) nach Delphi
Mathe? 0xF0 = $F0 oder 240 = 0..239
Code:
Hier ist es egal, da ALIGN immer nur das Maximum angibt und da bei dem Ding alles nur Bytes sind, ist es da immer 1 aka PACKED.
typedef struct My_INFO_S
{ My_BYTE reserved_b_00[0xF0]; My_BYTE reserved_b_10[0x2FC]; } BYTE_PACKED_ALIGN4 /* PPC_BYTE_PACKED */ My_INFO_T; |
AW: C++ DLL (Funktion) nach Delphi
Zitat:
Ist das ein Array welches so aussehen würde?
Delphi-Quellcode:
Wenn das richtig wäre, dann müsste ja folgende Deklaration im C++
reserved_b_00 : array[0..239] of Byte; //0xF0 = 240
reserved_b_10 : array[0..763] of Byte; //0x2FC = 764
Delphi-Quellcode:
im Delphi so aussehen:
reserved_b_00[0x8000]
Delphi-Quellcode:
Verdammt großes array oder?
reserved_b_00: array[0..32767] of Byte; //0x8000 = 32768
|
AW: C++ DLL (Funktion) nach Delphi
So ist es aber.
|
AW: C++ DLL (Funktion) nach Delphi
ok danke für die Info, mir war nur eben nicht ganz klar, ob die array Übernahme in Delphi so richtig ist. Danke
|
AW: C++ DLL (Funktion) nach Delphi
Ich muss leider nochmal etwas nachfragen weil das für mich auch nicht verständlich ist und ihr könnt mir das evtl. erklären.
Deklaration in C++:
Delphi-Quellcode:
In der C-Datei wird "global_pRam" an einer Stelle befüllt und an ganz vielen Stellen abgefragt und beschrieben.
typedef struct My_Struct_S
{ Record1 rec1; Record2 rec2; Record3 rec3; } PPC_BYTE_PACKED My_Struct_T; My_Struct_T volatile *global_pRam = NULL; Befüllt:
Delphi-Quellcode:
Deklaration der Funktion "My_get_pointer":
My_get_pointer(MyHandle, TIMEOUT_ms, &global_pRam, &my_ErrStruct);
Delphi-Quellcode:
In der C-Datei wird von "global_pRam" in einer Schleife eine Variable abgefragt und innerhalb der Schleife wird etwas gesetzt von "global_pRam". Das ist eine While Schleife, die sozusagen einen Status abfragt und innerhalb der Schleife wird durch eine andere Funktion etwas gesetzt, was dann den Status ändern müsste, sodass dieser auch wieder abgefragt werden kann.
My_DWORD My_get_pointer (
My_DWORD my_handle, // in My_DWORD timeout, // in My_Struct_T volatile **data, // out My_ERROR_T *err); // out
Delphi-Quellcode:
Meine Umsetzung im Delphi sieht jetzt so aus:
while(global_pRam->rec1.state != NewState)
{ /* tue irgendwas... set_modus(myHandle, NewState,&my_ErrStruct); while(global_pRam->rec1.state != my_NewSwMode && TimeoutMs < 5000) { Sleep(50); TimeoutMs +=50; } if(TimeoutMs >= 5000) { /* state not changed after ms } else { /* state successfully changed */ TimeoutMs = 0; } }
Delphi-Quellcode:
Meine konkrete Frage ist nun:
global_pRam: PMy_Struct;
New(global_pRam); My_get_pointer(MyHandle, 5000, global_pRam, @my_ErrStruct); Muss ich das "volatile" irgendwie im Delphi berücksichtigen? Anscheind muss sich innerhalb dieser while Schleife die Werte hinter dem Pointer ändern, sodass ich überhaupt auf Änderung reagieren kann. Ist das dann so richtig, dass ich vorher einfach das New aufrufe und dann die Funktion "My_get_pointer"? Ändern sich die Werte dann genauso hinter dem Zeiger, denn die Funktion "My_get_pointer" ist in einer DLL, welche ich aufrufe. Also müsste sich ja der Inhalt der Variablen hinter dem Zeiger ändern obwohl diese aus einer DLL kommen. Vielleicht habt ihr da noch ein paar Anregungen. |
AW: C++ DLL (Funktion) nach Delphi
Folgende Anmerkung noch aus dem Handbuch für die C-Datei:
Der Funktionsaufruf „my_get_pointer“ liefert die Basisadresse (C-Zeiger) auf die Struktur My_Struct_T. Mit diesem C-Zeiger kann Ihr Programm hochperformant auf die Daten im zugreifen. Also muss das ja ein Zeiger sein, den ich von dem Aufruf zurückgemeldet bekomme und worin sich die Daten anscheind immer ändern können. |
AW: C++ DLL (Funktion) nach Delphi
Zeig mal bitt Deine Delphi Deklaration von
My_get_pointer Wenn ich das richtig verstehe wird der Pointer in der c dll belegt. Gibt es auch eine function zur freigabe? |
AW: C++ DLL (Funktion) nach Delphi
ja es gibt auch eine Funktion für die Freigabe.
Hier die Deklaration:
Delphi-Quellcode:
function My_get_pointer(Handle: LongWord; TimeOut : LongWord; my_struct: PMy_Struct; aError: PERROR): LongWord;stdcall;external DP_DLL;
|
AW: C++ DLL (Funktion) nach Delphi
Zitat:
Die Dll liefert Dir den Pointer auf das Struct zurück. Du musst nicht selber Speicher belegen. |
AW: C++ DLL (Funktion) nach Delphi
Zitat:
Entweder
Delphi-Quellcode:
my_struct: PMy_Struct
oder
Delphi-Quellcode:
var my_struct: TMy_Struct
Delphi-Quellcode:
var my_struct: PMy_Struct
ist doppelt gemoppelt (= falsch). |
AW: C++ DLL (Funktion) nach Delphi
Zitat:
Delphi-Quellcode:
bzw.
MyStruct*
Delphi-Quellcode:
als Parameter in C/C++ bedeutet, dass du selbst einen Zeiger/Referenz übergibst. Den Speicher für das dahinterliegende Struct musst du durchaus selbst (entweder auf dem Stack oder dem Heap) bereitstellen. Als Zeiger/Referenz übergibt man die Structs, wenn man deren Inhalt ändern möchte (C/C++ kennt kein
MyStruct&
Delphi-Quellcode:
).
var
Delphi-Quellcode:
sieht man auch ab und zu, wobei es sich hierbei nur um eine manuelle Optimierung handelt, damit der Inhalt der
const MyStruct*/&
Structs beim Aufruf nicht auf den Stack gepusht werden. Wie Neutral General schon angedeutet hat, ist
Delphi-Quellcode:
äquivalent zu
MyStruct*
Delphi-Quellcode:
in Delphi, was wiederrum äquivalent zu
var (T)MyStruct
Delphi-Quellcode:
ist.
PMyStruct
Zitat:
Delphi-Quellcode:
bzw.
MyStruct**
Delphi-Quellcode:
:-D
MyStruct*&
Edit: Falsch gelesen, ist ja sogar
Delphi-Quellcode:
:wall:
void**
|
AW: C++ DLL (Funktion) nach Delphi
Nee
Zitat:
Delphi-Quellcode:
data is als Pointer auf Pointer definiert also ein var zu einem Pointer.
My_DWORD My_get_pointer (
My_DWORD my_handle, // in My_DWORD timeout, // in My_Struct_T volatile **data, // out //Pointer auf Pointer My_ERROR_T *err); // out Man könnte auch
Delphi-Quellcode:
type
PPMy_Struct = ^PMy_Struct; // und dann function My_get_pointer(Handle: LongWord; TimeOut : LongWord; my_struct: PPMy_Struct; aError: PERROR): LongWord;stdcall;external DP_DLL; |
AW: C++ DLL (Funktion) nach Delphi
Ich versuche das gleich mal.
Muss ich denn ein New(my_struct) vorher machen oder nicht? |
AW: C++ DLL (Funktion) nach Delphi
Zitat:
|
AW: C++ DLL (Funktion) nach Delphi
So wie ich es aus Deiner Dokumentation gelesen habe nicht.
Zitat:
|
AW: C++ DLL (Funktion) nach Delphi
ja eine extra Funktion zum freigeben gibt es auch tatsächlich.
ich teste gleich mal und gebe die Info ob es geht Edit: Funktioniert. Coole Sache, Danke!! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:58 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