Wie kann man Struktur oder Pointer als Rückgabewert aus DLL realisieren ?



  • Hallo zusammen,

    ein weiteres Problem, das ich gerade habe, ist es eine Struktur aus einer statischen MFC DLL zurückzugeben.

    struct MEINESTRUCT
    {
       int zahl1[30][30];
       int zahl2;
    };
    

    wenn ich nun folgende Funktion erstelle:

    MEINESTRUCT meinedllklasse::meinefunktion()
    {
       MEINESTRUCT value={0};
       return value;
    }
    

    und in der .def exportiere, kommt in der EXE Datei beim Aufruf der exportierten Funktion ein:

    Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

    zurück.

    Auch wenn ich hier einen Pointer auf die Struktur verwende, kommt selbige Meldung. So wie ich das sehe, müssten die zwei Strukturen von der EXE und der DLL verschieden sein, um diese Meldung zu erzeugen, das ist hier nicht der Fall.
    Ich hab dann eine Struktur als globale Variable in der DLL erzeugt, um den Pointer evtl. zu erhalten, aber auch dass funktionerte nicht 😞

    MEINESTRUCT value={0};
    
    MEINESTRUCT* meinedllklasse::meinefunktion()
    {
       return &value;
    }
    

    Also wie überträgt man eine Struktur richtig ?

    Grüße
    thenoname



  • Wenn ich mir die Fehlermeldung so anschaue, liegts eher an der Aufrufkonvention als an der Struktur. Hast du evtl. cdecl und stdcall vermischt?

    Wie sieht der Typ des Funktionszeigers in deinem Hauptprogramm aus?



  • Ursprünglich hatte ich ohne Pointer:

    struct MEINESTRUCT
    {
       int zahl1[30][30];
       int zahl2;
    };
    
    typedef MEINESTRUCT (*meineexeaufruffunktion) ();
    meineexeaufruffunktion meinefunktion = {NULL};
    

    DLL link mit:

    meinefunktion = (meineexeaufruffunktion) GetProcAddress (hDLLScann, "meinefunktion");
    

    Ausführung der DLL Funktion:

    MEINESTRUCT value = meinefunktion();
    

    Hoffe das gibt dir einen Hinweis ...
    ich hatte nirgends einen stdcall definiert, dann sollte es doch cdecl sein ?

    Grüße
    thenoname



  • Hm also wenn man nichts angibt, ist es normalerweise cdecl, ja. Allerdings weis ich nicht wie das bei MFC-DLLs ist. Ich hab bisher nur mit regulären gearbeitet.

    Mach doch einfach schnell 2 Tests: ersetze deine Struktur durch int. Wenn der Fehler immer noch eintritt, liegt es nicht an der Struktur (was ich denke).

    Und dann setze einfach mal explizit die Aufrufkonvention und schaue, ob es dann funktioniert.



  • Hi,

    also wie gesagt, der Pointer will auch nicht, das ist schon ein DWORD.
    Ich habs aber nochmals mit int ausprobiert, gleiches Verhalten.
    Ich weiss leider auch nicht, wie es sich mit statischen MFC-DLLs verhält.

    Wie sollte die Declaration aussehen ? stdcall ? Kannst du mir das mal zu Sicherheit in etwa angeben wie du es für Richtig hälst ?

    Grüße
    thenoname



  • Benutzen DLL und Anwendung auch die gleiche Datenausrichtung (alignment)?



  • Ein einfaches "int" hat eine Datenausrichtung ?



  • mach mal aus

    typedef MEINESTRUCT (*meineexeaufruffunktion) ();
    

    das:

    typedef MEINESTRUCT __stdcall (*meineexeaufruffunktion) ();
    

    Evtl haut der die in der MFC-DLL doch nicht als cdecl raus.



  • Ein einzelnes int nicht, aber eine Struktur. Probiere mal

    #pragma pack(push, 1)
    
    struct MEINESTRUCT
    {
       int zahl1[30][30];
       int zahl2;
    };
    
    #pragma pack(pop)
    


  • Evtl haut der die in der MFC-DLL doch nicht als cdecl raus.

    Gibt es eigentlich irgendeinen Dependency Walker Clone, der mir diese
    Typarten anhand einer x-beliebigen DLL-Datei anzeigt ? Nachdem ich es hier nicht weiss,
    wäre das jetzt echt hilfreich !

    #pragma pack(push, 1)
    

    Gute Idee, besonderst bei _stdcall oder _cdecl Unterschied.
    Kommt die Meldung auch, wenn die Parameterübergabe fehlschlägt ?
    Ich habe gelesen, das es Probleme mit (void) gibt, also ein Unterschied zwischen
    () und (void) Übergaben.

    Grüße
    SirNoName



  • Also ich bin am verzweifeln. Auf einigen Web Seiten fand ich Infos darüber,
    das es ein Debug-Comiler Fehler sei und man "Beide (/RTC1 entspricht /RTCsu)"
    auf Standard stellen sollte. Dannach klappt der DLL Zugriff tatsächlich.
    Nach 4 mal ist jedoch das Client Programm total zerschossen und dessen
    Variablen total falsch im Wert. Nach 5 zugriffen merkt dies dann der Debugger.

    Ich sehe auch nur Tuts im Netz, die die passende .lib der DLL inkludieren.
    Das kann ich jedoch nicht machen.

    __stdcall gibt keine Änderung, __cdecl im Client ergibt Schwierigkeiten.

    Wie könnte man noch DLL Funktionen im CLient deklarieren ?

    Dieselbe DLL nicht als MFC statisch sondern als shared compiliert funktioniert
    fehlerfrei, nur das statische kompilieren erzeugt solche ESP Fehler.

    Grüße
    thenoname


Anmelden zum Antworten