Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Fehler beim Laden einer C++-DLL in Delphi (https://www.delphipraxis.net/130796-fehler-beim-laden-einer-c-dll-delphi.html)

Endgegner 13. Mär 2009 09:53


Fehler beim Laden einer C++-DLL in Delphi
 
Hallo zusammen,

ich hoffe sehr, dass ihr mir helfen könnt. Ich sitze gerade auf der Arbeit und suche verzweifelt die Ursache eines Fehlers. Das Hauptprogramm ist in Delphi geschrieben und ich schrieb vor einiger Zeit eine Software-API (als DLL) für ein Hardwäregerät in C++. Ich habe schon vor einiger Zeit die Software-API für die Hardware in das Delphi-Programm eingebunden, doch mir ist bei einem Langzeittest ein Fehler begegnet. Wenn die Kommunikation zu dem Gerät beendet wird und viele Zeit später (etwa eine Stunde oder mehr) die Verbindung wieder hergestellt wird, kommt folgende Fehlermeldung:
Zitat:

The value of ESP was not properly saved across a function call. This is usally a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
Ich habe natürlich ausgiebig recherchiert und es ist meist auf Unregelmäßigkeiten beim Funktionsaufruf zurückzuführen. Doch leider habe ich keine Ahnung, was ich falsch gemacht habe. Das Problem tritt, wie bereits gesagt, erst nach einiger Zeit auf.

So in etwa würde eine Funktion in der C++-Source-Datei der DLL aussehen:
Delphi-Quellcode:
_declspec(dllexport) Status Funktionsname()
{
   // Quellcode

   return RESULT_OK;
}
In der Delphi-Unit sieht das ganze so aus:
Delphi-Quellcode:
Funktionsname = function(): Integer; cdecl;
Und natürlich noch das Laden der Funktion aus der DLL:
Delphi-Quellcode:
function LoadFunctions(var API: DeviceAPI): Boolean;
    begin;
      Result := False;
      with API do
        begin
          if (ApiDll <> 0) then
            FreeLibrary(ApiDll);
          ApiDll := LoadLibrary(RIGHT_PATH);
          if (ApiDll <> 0) then
            begin
              FN := GetProcAddress(ApiDll, 'Funktionsname');
...
Ich muss doch, nach meinem Verständnis, cdecl benutzen, weil es sich um C++-Funktionen in der DLL handelt. Das Laden der Funktion geschieht auch offensichtlich korrekt, da sonst der Fehler schon sofort auftreten würde. Wo aber liegt dann meine Verletzung mit den Zeigern, von der die Fehlermeldung spricht?!?

Ich wäre für eure Hilfe sehr dankbar.

P.S: Die DLL wird dynamisch zur Laufzeit geladen, da das Hardware-Device nur auf Anfrage benutzt wird.

blauweiss 13. Mär 2009 10:14

Re: Fehler beim Laden einer C++-DLL in Delphi
 
Hallo Endgegner,

wie ist der Typ Status definiert ?

Blausweiss

Endgegner 13. Mär 2009 10:21

Re: Fehler beim Laden einer C++-DLL in Delphi
 
Delphi-Quellcode:
typedef short int   Status;
Dies sollte mit dem Integer-Datentyp in Delphi verträglich sein. Die Rückgabewerte der Funktionen sind alles Zahlenkonstanten. Also das "RESULT_OK", das in der Beispielsfunktion zurückgegeben wird, wurde in der C++-Source-Datei definiert als
Delphi-Quellcode:
#define RESULT_OK    0
Ein Konflikt mit Datentypen habe ich für mich ausgeschlossen, nachdem ich alle vorkommenden Variablen in der Delphi-Unit mit denen in der C+-Datei verglichen hatte.

DMW 13. Mär 2009 11:03

Re: Fehler beim Laden einer C++-DLL in Delphi
 
Zitat:

Zitat von Endgegner
Delphi-Quellcode:
typedef short int   Status;
Dies sollte mit dem Integer-Datentyp in Delphi verträglich sein.

Nicht ganz; Integer ist 32 Bit breit, short int aber nur 16.

Interessant für die weitere Analyse wäre, wenn du den Fehler im Debugger reproduzieren könntest und dann die Signaturen genau der Funktion, bei deren Aufruf es auftritt in C++ und Delphi näher betrachtest (-> Call-Stack).

Tyrael Y. 13. Mär 2009 11:11

Re: Fehler beim Laden einer C++-DLL in Delphi
 
Zitat:

Bei allen Konventionen mit Ausnahme von cdecl entfernt die Prozedur bzw. Funktion die Parameter vom Stack, sobald die Steuerung zurückgegeben wird. Bei der Konvention cdecl entfernt die aufrufende Routine die Parameter vom Stack, sobald sie wieder die Steuerung erhält.
Ist das vielleicht dein Fehler?

btw: cdecl hat nichts mit mit C++ zu tun, probier mal bei dir stdcall

Edit: Hier siehts du auch dein Problem genau beschrieben

Hier!

...entweder du kümmerst dich selbst drum den Stack wieder in den richtigen Zustand zu kriegen oder du benutzt stdcall.

Endgegner 13. Mär 2009 11:24

Re: Fehler beim Laden einer C++-DLL in Delphi
 
Ich werde gleich mal wieder das Programm starten und nach Reproduktion des Fehlers (dauert leider min. eine Stunde, siehe Ausgangsthread) werde ich mir, wenn möglich, den Aufrufstack anschauen. Danke für den Tipp, daran hatte ich noch gar nicht gedacht.

Die Seite zum Thema Aufrufkonventation hate ich bereits durchgelesen und auch wenn ich
Delphi-Quellcode:
Funktionsname = function(): Integer; cdecl;
zu
Delphi-Quellcode:
Funktionsname = function(): Integer; stdcall;
ändere, macht es keinen Unterschied! Ich habe bevor ich hier den Ausgangspost schrieb, bereits länger nach der Fehlermeldung und den verschiedenen Aufrufarten recherchiert.

sirius 13. Mär 2009 11:30

Re: Fehler beim Laden einer C++-DLL in Delphi
 
Wenn die Funktion nicht all zu lang ist, könntest du mal den ASM-Code aus dem CPU-Fenster hier posten.

DMW 13. Mär 2009 12:07

Re: Fehler beim Laden einer C++-DLL in Delphi
 
Zitat:

Zitat von Tyrael Y.
btw: cdecl hat nichts mit mit C++ zu tun

:gruebel:
cdecl ist die Standard-Aufrufkonvention in C++ (es sei natürlich denn, du änderst das über einen Compilerswitch).

Tyrael Y. 13. Mär 2009 12:16

Re: Fehler beim Laden einer C++-DLL in Delphi
 
Zitat:

Zitat von DMW
Zitat:

Zitat von Tyrael Y.
btw: cdecl hat nichts mit mit C++ zu tun

:gruebel:
cdecl ist die Standard-Aufrufkonvention in C++ (es sei natürlich denn, du änderst das über einen Compilerswitch).

Ich weiss, ich wollte nur ausdrücken, dass es nicht rein C++ basiert ist, es ist nicht sprachgebunden.

Endgegner 13. Mär 2009 13:03

Re: Fehler beim Laden einer C++-DLL in Delphi
 
Nach einem weiteren Testlauf, habe ich geschaut, an welcher Stelle es genau knallt. Der Fehler tritt, wie im Ausgangspost beschrieben, auf, wenn man nach längerer Pause die Kommunikation zu dem Hardwaregerät wieder startet. Die Fehlermeldung kommt genau dann, wenn im Hauptprogramm (Delphi) die Kommunikation wieder aufgenommen wird und die dazugehörigen Funktionen aus der Software-API (die DLL in C++) geladen werden sollen.

Ist es irgendwie möglich, dass das Delphi-Programm die Verbindung zur Software-API, also besser gesagt zur DLL, verlieren könnte und damit die Zeiger ins Nirgendwo zeigen?


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:18 Uhr.
Seite 1 von 2  1 2      

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