Wie Arrayinhalt in Klasse/Struktur kopieren?



  • Hallo!

    Ich habe eine Klasse, die aus einem Flashspeicher einzelne Bytes ausliest. Diese Bytes sollen letztendlich direkt in eine Klasse geschrieben werden.

    Beispiel:

    class A {
    public:
        int m_a;
    };
    
    class B : public A {
    public:
    
        char c;
        int b;
    };
    

    Per sizeof kann ich jetzt erfahren, wie groß B in Bytes ist. Einzelne Bytes kann ich wie geschrieben nacheinander auslesen.

    Wie schiebe ich nun die Informationen am elegantesten in B rein? Könnte ich z.B. die Bytes in einem Array zwischenspeichern

    BYTE arr[3]
    

    und dann mit memcpy arbeiten?

    memcpy ( myB, arr, sizeof(B) );
    

    Gibt es eine alternative Lösung 😕 😋 ?



  • Es ist nicht ganz klar, was Du vorhast. Was steht den genau in dem Flashspeicher drin?
    Ist es ein binäres Abbild eines Objekts der Klasse B oder gibt es da ein bestimmtes Format?

    Konkreter gefragt - welche Bedeutung hat ein Byte im Flashspeicher an der Position 'idx'?


  • Mod

    ArrayIndex schrieb:

    Hallo!

    Ich habe eine Klasse, die aus einem Flashspeicher einzelne Bytes ausliest. Diese Bytes sollen letztendlich direkt in eine Klasse geschrieben werden.

    Beschreib genau, was du möchtest. "Reinschreiben" kann vieles bedeuten. Beschreib am besten dein Ziel, nicht wie du dir die Lösung vorstellst.

    und dann mit memcpy arbeiten?

    memcpy ( myB, arr, sizeof(B) );
    

    Das fällt sicherlich unter eine mögliche Definition von "reinschreiben". Dennoch werde ich den Verdacht nicht los, dass dies nicht das tut, was du eigentlich erwartest. Welche Werte sollen B::m_a, B::c und B::b hinterher haben? Spielt das überhaupt eine Rolle?

    Gibt es eine alternative Lösung 😕 😋 ?

    Siehe oben.



  • Werner Salomon schrieb:

    Es ist nicht ganz klar, was Du vorhast. Was steht den genau in dem Flashspeicher drin?
    Ist es ein binäres Abbild eines Objekts der Klasse B oder gibt es da ein bestimmtes Format?

    Konkreter gefragt - welche Bedeutung hat ein Byte im Flashspeicher an der Position 'idx'?

    Im Flash liegt ein binäres Abbild eines Objekts der Klasse B, dass ich wieder auslesen möchte.



  • Ok - angenommen Du weißt, dass das Objekt b der Klasse B ab 'myB' im Speicher liegt.
    Dann könntest Du auch schlicht schreiben:

    const unsigned char* myB = position_im_Flashspeicher;
        B neues_B = *reinterpret_cast< const B* >( myB );
    

    Gruß
    Werner



  • Werner Salomon schrieb:

    Ok - angenommen Du weißt, dass das Objekt b der Klasse B ab 'myB' im Speicher liegt.
    Dann könntest Du auch schlicht schreiben:
    C++:
    const unsigned char* myB = position_im_Flashspeicher;
    B neues_B = *reinterpret_cast< const B* >( myB );

    Das ist eine Möglichkeit, die aber nur dann funktioniert, wenn Du a) direkt an den Speicher rankommst, der b) linear addressierbar ist und c) keine virtuellen Funktionen in der Klasse genutzt werden, die, einmal persistiert, den vtbl Pointer mit hoher Wahrscheinlichkeit ungültig werden lassen.

    Dennoch: Wenn obige Bedingungen erfüllt sind, ist das ein guter Ansatz. Ansonsten, kannst Du einen Konstruktor schreiben, der jeweils die Daten aus einem Array, dass Du ggf. vorher aus dem Flash füllst, übergeben bekommt.



  • Also bei den Beschreibungen kräusseln sich einem schon die Fingernägel bisserl ^^

    Im Flash liegt ein binäres Abbild eines Objekts der Klasse B

    Wie wird die in den Speicher serialisiert ?
    Wer tut das?
    Hasst du Bibs womit Du eine äquivalent der Klasse aus einem Datenstrom wieder desectieren kannst ?
    Hasst du eine Binäre "Beschreibung", wo was und wie abgelegt wird ?

    Wenn du alle diese Fragen mit "Nein" oder Schulterzucken beantworten kannst / musst, solltest Du lieber die Hände davon lassen ...

    Das ist eine Möglichkeit, die aber nur dann funktioniert, wenn Du a) direkt an den Speicher rankommst, der b) linear addressierbar ist und c) keine virtuellen Funktionen in der Klasse genutzt werden, die, einmal persistiert, den vtbl Pointer mit hoher Wahrscheinlichkeit ungültig werden lassen.

    Solange Du nicht weisst, wo die Daten herkommen, kannst du nich mal davon ausgehen das du Binaerkompatible Datentypen hasst ^^

    Was ist wenn das wer aus python oder C# oder so ne MFC-Serialization / boost-Serialize ist ?
    Da fehlen viel zu viele Infos um da ueberhaupt annahmen machen zu können !

    Ciao ...



  • Bibs

    Ich dachte zuerst an Biber, klasse 😃 👍



  • Libs waere doch zu langweilig 😃



  • @vtbl: Punkt a) und b) habe ich implizit als selbstverständlich vorausgesetzt. Sonst geht auch memcpy nicht.

    Zu Punkt c.) - genau das ist der Vorteil der Zuweisung gegenüber dem memcpy . Die vtbl des Objekts im Flashmemory kann ja bereits vor dem Kopieren ungültig sein. Mit einem memcpy zerstört man demzufolge auch eine vtbl des Ziels.
    Genau das passiert bei der Zuweisung nicht.
    Es versteht sich weiter von selbst, dass im Objekt B keine Zeiger oder Objekte mit Zeigern (std::string) vorhanden sein dürfen.
    Viel wichtiger in diesem Zusammenhang ist, dass das schreibenden und das lesende Programm mit dem gleichem Compiler mit identischen Optionen übersetzt worden ist. Ansonsten kann es sein, dass B != B ist.

    Ich behaupte mal, dass das in der Praxis auch mit Klassen mit virtuellen Methoden funktioniert. Es darf nur keine Methode des Objekts im Flashmemory ausgerufen werden - auch und gerade nicht im Zuweisungsoperator.

    Anbei ein Programmschnipsel zu Spielen:

    #include <iostream>
    
    class A
    {
    public:
        explicit A( double a ) : m_a( a ) {}
        virtual ~A() =0;
        virtual int egal() =0;
    protected:
        double m_a;
    };
    inline A::~A() {}
    
    class B : public A
    {
    public:
        B( double a, int i )
            : A( a )
            , int_( i )
        {}
        virtual int egal()
        {
            std::cout << "B(" << m_a << ")" << std::endl;
            return int(int_);
        }
    private:
        int int_;
    };
    
    int main()
    {
        using namespace std;
        unsigned char flashmemory[200];
        {
            const B b( 1.23456, 7);
            memcpy( flashmemory, &b, sizeof(b) );
        }
        A* a = new B( *reinterpret_cast< const B* >( flashmemory ) );
        const int i = a->egal();
        cout << i << endl;
        delete a;
    
        return 0;
    }
    

    Gruß
    Werner



  • RHBaum schrieb:

    Also bei den Beschreibungen kräusseln sich einem schon die Fingernägel bisserl ^^

    Im Flash liegt ein binäres Abbild eines Objekts der Klasse B

    Wie wird die in den Speicher serialisiert ?
    Wer tut das?
    Hasst du Bibs womit Du eine äquivalent der Klasse aus einem Datenstrom wieder desectieren kannst ?
    Hasst du eine Binäre "Beschreibung", wo was und wie abgelegt wird ?

    Wenn du alle diese Fragen mit "Nein" oder Schulterzucken beantworten kannst / musst, solltest Du lieber die Hände davon lassen ...

    Das ist eine Möglichkeit, die aber nur dann funktioniert, wenn Du a) direkt an den Speicher rankommst, der b) linear addressierbar ist und c) keine virtuellen Funktionen in der Klasse genutzt werden, die, einmal persistiert, den vtbl Pointer mit hoher Wahrscheinlichkeit ungültig werden lassen.

    Solange Du nicht weisst, wo die Daten herkommen, kannst du nich mal davon ausgehen das du Binaerkompatible Datentypen hasst ^^

    Was ist wenn das wer aus python oder C# oder so ne MFC-Serialization / boost-Serialize ist ?
    Da fehlen viel zu viele Infos um da ueberhaupt annahmen machen zu können !

    Ciao ...

    So ein Unfug. Echt mal. Hier waren eine Menge sinnvolle Antworten im Thread, deine gehört NICHT dazu. Aus Gründen der Einfachheit habe ich angegeben was wichtig ist. Und wenn ich schreibe das ein Objekt bzw. das Binäre Abbildung davon im Flash liegt, dann liegt es da. Warum und wieso ist für die Frage total unerheblich.

    Man kann aus einer einfachen Frage auch ein Riesenproblem machen.


  • Mod

    ArrayIndex schrieb:

    So ein Unfug. Echt mal. Hier waren eine Menge sinnvolle Antworten im Thread, deine gehört NICHT dazu. Aus Gründen der Einfachheit habe ich angegeben was wichtig ist. Und wenn ich schreibe das ein Objekt bzw. das Binäre Abbildung davon im Flash liegt, dann liegt es da. Warum und wieso ist für die Frage total unerheblich.

    Als langfristiger Leser weiß RHBaum, dass die von dir gezeigte Vorgehensweise auch die typische Art und Weise ist, wie Leute ohne Ahnung Klassen serialisieren, die man nicht so serialisieren kann.



  • SeppJ schrieb:

    ArrayIndex schrieb:

    So ein Unfug. Echt mal. Hier waren eine Menge sinnvolle Antworten im Thread, deine gehört NICHT dazu. Aus Gründen der Einfachheit habe ich angegeben was wichtig ist. Und wenn ich schreibe das ein Objekt bzw. das Binäre Abbildung davon im Flash liegt, dann liegt es da. Warum und wieso ist für die Frage total unerheblich.

    Als langfristiger Leser weiß RHBaum, dass die von dir gezeigte Vorgehensweise auch die typische Art und Weise ist, wie Leute ohne Ahnung Klassen serialisieren, die man nicht so serialisieren kann.

    Dann nehme ich meine Kritik zurück ⚠



  • Und wenn ich schreibe das ein Objekt bzw. das Binäre Abbildung davon im Flash liegt, dann liegt es da. Warum und wieso ist für die Frage total unerheblich.

    Da du die Form als unerheblich betrachtest, kann man eigentlich nur davon ausgehen, dass du lesen und schreiben gleichermassen in der Hand hasst, also Dein Code ist ... richtig ?

    Dann wuerd ich Dir sowieso empfehlen, ein (binaer) Serialize Framework zu verwenden ....
    z.b. boost::serialize

    Falls du es unbedingt von Hand selber machen willst, wegens dem lerneffekt, dann macht man das "üblicherweisse" mit binaerstreams !

    std::ifstream infile("C:\\myfile.bin",ios::in | ios::binary);
    if(in.is_open())
    {
        int value;
        infile >> value; /// sollte nun den serialisierten Wert haben
    }
    

    wegschreiben dann entsprechend mit ofstream und dem << operator

    Leider gibts noch kein fertigen << >> operator für stl container (ausser std::string, aber der iss bissi tricky für binaere streams).

    Aber wenn alle Elemente den >> und << operator implementieren ist das selber zu bauen wiederum trivial. Mann muss nur zuerst die Groesse wegspeichern ...
    Danach jedes einzelnhe element ...
    Bein einlesen andersrum ... groesse lesen, schleife 0 ... n-1, Object konstruieren, aus dem stream lesen lassen, in den container einfuegen ...

    Wenn Performance nen Problem, und mann Massen Daten an POD's hat, kann man natürlich den Operator fuer speziell den std::vector<PODTyp> so überladen, das er memcpy nimmt!

    Vioala, fertig

    bei klassen sieht es besonders c++ like aus, wenn man den >> << operator fuer die klasse überlaed.

    Hirariche Klassenstrukturen sind etwas komplexer, gehen aber auch so ....

    Kommt noch Virtualitaet hinzu, wirds noch ne nummer komplizierter. Da werden dann "class factories" bzw. "factory methods" schnell Pflicht.

    Ciao ....


Anmelden zum Antworten