DLL Datentypen



  • Moin,moin.

    Ich habe folgenden Code, der das API einer DLL darstellen soll:

    #pragma once
    #ifndef _MAIN_H_
    #define _MAIN_H_
    #include <string>
    
    namespace foo {
    	struct result {
    		std::string timestamp;
    		double ut0;
    		double ut90;
    		double it0;
    		double it90;
    		double urec0;
    		double urec90;
    		double unm0;
    		double unm90;
    		double stDevIT;
    		double stdDevURec;
    		double stdDevUmn;
    		double r2p;
    		double phase2p;
    		double ci;
    		double ip;
    		double sUt0;
    		double sUt90;
    		double sUrec0;
    		double sUrec90;
    		double sIt0;
    		double sIt90;
    		double sUnm0;
    		double sUnm90;
    		double rho;
    		double ip4p;
    		double adcMinCh0;
    		double adcMaxCh0;
    		double adcMinCh1;
    		double adcMaxCh1;
    		double adcMinCh2;
    		double adcMaxCh2;
    		double adcMinCh3;
    		double adcMaxCh3;
    		double adcMinCh4;
    		double adcMaxCh4;
    		double adcMinCh5;
    		double adcMaxCh5;
    		int messtyp;
    		int slideID;
    		double uOut;
    	};
    
    	extern "C" __declspec(dllexport) bool StartMeasureLoop(std::string databaseFileName, void(*GetResultCallback)(foo::result result), std::string &error);
    
    	extern "C" __declspec(dllexport) bool StartMeasure(std::string databaseFileName, void(*GetResultCallback)(foo::result result), int measureId, std::string &error);
    
    	extern "C" __declspec(dllexport) bool StopMeasure(std::string &error);
    }
    #endif
    

    Wenn ich die DLL so erstelle, treten merkwürdige Speicherfehler auf, wenn ich sie in einem anderen C++ Programm benutzen will.

    Ich vermute, dass es an den Datentypen der Parameter liegt... 😕

    Ich hoffe, dass mir da jemand weiterhelfen kann und bedanke mich im Voraus 🙂

    Lg Henrik 🙂


  • Mod



  • Soweit ich weiß ist es problematisch Container aus der Standardlib (z.b. std::string) als Parameter ener exportieren Funktion zu nutzen.
    Außerdem musst du bei structs als Parameter auf das Padding aufpassen.



  • DarkShadow44 schrieb:

    Soweit ich weiß ist es problematisch Container aus der Standardlib (z.b. std::string) als Parameter ener exportieren Funktion zu nutzen.
    Außerdem musst du bei structs als Parameter auf das Padding aufpassen.

    Wem soll das Blabla helfen?



  • manni66 schrieb:

    DarkShadow44 schrieb:

    Soweit ich weiß ist es problematisch Container aus der Standardlib (z.b. std::string) als Parameter ener exportieren Funktion zu nutzen.
    Außerdem musst du bei structs als Parameter auf das Padding aufpassen.

    Wem soll das Blabla helfen?

    Jedem der Google nutzen kann ? 🙄
    Spätestens wenn du die DLL mit einem anderen Compiler und anderen Settings kompilierst fliegt dir das so wie es jetzt ist um die Ohren.



  • Hä, sollte man die extern "C" - Funktionen nicht außerhalb des Namespaces definieren? Sonst würde das extern "C" doch keinen Sinn machen?



  • Außerdem musst du bei structs als Parameter auf das Padding aufpassen.

    das heißt letztendlich? Soll man die structs packen?



  • Tim06TR schrieb:

    Außerdem musst du bei structs als Parameter auf das Padding aufpassen.

    das heißt letztendlich? Soll man die structs packen?

    Genau. Sonst läufst du Gefahr dass 2 Compiler die struct anders anlegen, und das willst du nicht. "#pragma pack 1" sollte reichen. Es wird wahrscheinlich auch ohne gehen, aber sicher ist sicher.

    Mr.Long schrieb:

    Hä, sollte man die extern "C" - Funktionen nicht außerhalb des Namespaces definieren? Sonst würde das extern "C" doch keinen Sinn machen?

    Naja es geht schon, allerdings verlierst du halt die Namespaceinformation weil C keine Namespaces kennt. Sollte sich genau gleich verhalten wie wenn man die Funktion außerhalb des Namespaces hat.



  • extern "C" ist aber sinnlos, wenn man C++ Datentypen (wie std::string) als Parameter (oder Rückgabewert) verwendet, da C damit ja nichts anfangen kann...

    Ein anderes C++ Programm dagegen (welches mit demselben(!) Compiler erstellt wurde), sollte aber die Funktionen benutzen können (dafür ist aber dann das extern "C" nicht notwendig)!

    PS: Die Callback-Funktion sollte den Parameter als "const foo::result& result" entgegennehmen, damit nicht die gesamte Struktur kopiert werden muß).



  • Ich kapere hier etwas den Thread, aber ich hätte gern zu seinen Fragen noch etwas mehr Details, da ich zufällig mich auch gerade zum ersten Mal etwas mit Bibliotheken beschäftige. (vorher hielt ich es für nicht notwendig)

    normalerweise würde ich alles außerhalb der lib alloziieren und einen Zeiger übergeben.
    Für strings müsste ich aber die Länge vorher wissen

    So wollte ich es machen: Der library eine alloc und dealloc Funktion für strings geben.

    PACK( // ist pragma pack 1 von allen compilern unterstützt? Hier mein altes compilerunabhängiges Pack macro.
    struct String {
        int size;
        char* data;
    });
    
    // Im Host:
    String* string = lib_get_some_string();
    dll_free_string(string);
    

    Wie macht man das, "wenn man weiß wie es gemacht wird" 😉



  • Th69 schrieb:

    extern "C" ist aber sinnlos, wenn man C++ Datentypen (wie std::string) als Parameter (oder Rückgabewert) verwendet, da C damit ja nichts anfangen kann...

    Nein, ist es nicht. Bei extern "C" geht es ums name mangling, und wenn du eine Funktion foo() in eine DLL exportieren willst, dann moechtest du die auch als "foo" wieder finden.

    Packing ist im Uebrigen komplett sinnlos, da Libs unter verschiedenen Compilern i.d.R. sowieso nicht kompatibel sind, u.A. wegen RTTI und Exceptions, aber auch weil stdlibs nicht kompatibel sind. Fuehrt hoechstens zu ineffizienterem Code.



  • Kellerautomat schrieb:

    Packing ist im Uebrigen komplett sinnlos, da Libs unter verschiedenen Compilern i.d.R. sowieso nicht kompatibel sind, u.A. wegen RTTI und Exceptions, aber auch weil stdlibs nicht kompatibel sind. Fuehrt hoechstens zu ineffizienterem Code.

    Boah, ey, du hast nichtmal gelesen was Tim06TR geschrieben hat, oder? Oder haperts echt am Verständnis?

    Nein, pragma pack ist NICHT sinnlos.
    Weil man mit C-artigen Interfaces wunderbar verschiedenste Compiler mischen kann.

    *facepalm*



  • Tim06TR schrieb:

    PACK( // ist pragma pack 1 von allen compilern unterstützt? Hier mein altes compilerunabhängiges Pack macro.
    struct String {
        int size;
        char* data;
    });
    
    // Im Host:
    String* string = lib_get_some_string();
    dll_free_string(string);
    

    Wie macht man das, "wenn man weiß wie es gemacht wird" 😉

    Ich würde sagen: ziemlich genau so.



  • hustbaer schrieb:

    Boah, ey, du hast nichtmal gelesen was Tim06TR geschrieben hat, oder? Oder haperts echt am Verständnis?

    Nein, pragma pack ist NICHT sinnlos.
    Weil man mit C-artigen Interfaces wunderbar verschiedenste Compiler mischen kann.

    *facepalm*

    Mit dem falschen Fuss aufgestanden? 😃
    a) gibt es Plattform ABIs, Compiler die sich nicht dran halten sind scheisse (hallo MSVC)
    b) ist es voelliger Bullshit, sich auf ein C Interface zu beschraenken
    c) kannst du mir nicht erzaehlen, dass es so unglaublich schwer ist, mit dem selben Compiler und Compilerflags wie der Anwendung zu kompilieren

    such dir was aus, ist mir zu bloed bei dem ton



  • Du hast vollkommen die Peilung verloren, oder?

    Kellerautomat schrieb:

    ist mir zu bloed bei dem ton

    Und mir bei dem sagenhaften Unsinn den du verzapfst.



  • Wieso sollte dann der Code mit den selben Libs nicht funzen? Er darf halt, wenn er einen anderen Compiler benutzt keine anderen Libs benutzen, sonst ist es ja klar, dass der Compiler evtl. falsche Offsets oder so benutzt.


Anmelden zum Antworten