Was ist ein Wrapper ?



  • Hallo was genau ist ein Wrapper ?
    Wofür braucht man einen Wrapper ?

    Aus dem Wikipedia Artikel wurde ich nicht schlau.

    Der Quelltext hab ich hier her: http://www.codeplanet.eu/tutorials/cpp/12-pointer-in-cpp.html

    #include <iostream>
    using namespace std;
    
    //Billig-Wrapper für ints, müssten natürlich noch Operatoren +, += usw. dazu
    class Integer 
    {
    public:
        explicit Integer(int i=0) : data(i) {}
        Integer(const Integer &i) : data(i.data) {}
        ~Integer() {}
    
        inline void setData(int i) { data = i; }
        inline int getData() const { return data; }
    
        Integer& operator=(int i) {
            data = i;
            return *this;
        }
    
        Integer& operator=(const Integer &i) {
            if (this == &i)
                return *this;
    
            data = i.data;
            return *this;
        }
    private:
        int data;
        operator int () const;
    };
    
    int main(int argc, char **argv) 
    {
        Integer myInt(7);
    
        Integer *pi = &myInt;
        (*pi).setData(12);
        cout << pi->getData() << '\n';  // Wir benutzen den Pfeil-Operator
        return 0;
    }
    

    Ich hab den mal etwas gekürtzt ist das jetzt auch noch ein Wrapper ?

    #include <iostream>
    using namespace std;
    
    class Integer
    {
    public:
    
        inline void setData(int i)
        {
              data = i;
         }
    
        inline int getData()
         {
              return data;
         }
    
    private:
        int data;
    
    };
    
    int main()
    {
    
        Integer myInt;
        Integer *pi=&myInt;
    
        (*pi).setData(12);
    
        cout << pi->getData() << '\n';  // Wir benutzen den Pfeil-Operator
    
    system("PAUSE");
    }
    


  • To wrap heisst nichts anderes als Einwickeln. Wenn dein Code etwas einwickelt, ist es ein Wrapper.



  • Das Beispiel ist irgendwo Käse, weil class Integer gegenüber int keinen Vorteil hat.
    Du hast jetzt lediglich ein paar Methoden (willkürlich) entfernt.

    Wrapperklassen kommen eigentlich dann zum Einsatz, wenn Code mit den vorgegebenen Klassen umständlich, fehleranfällig, einfach nur ungewohnt, usw ist. Häufig wrappt man C-Funktonen in einer Klasse.
    Oder absoluten LowLevel-Kram in Highlevel-Kram (direkte Zugriffe auf Audio-Devices in einfach zu nutzende Multimedia-Frameworks).
    Unumgänglich wird wrappen, wenn ein Programm Plattformunabhängig werden soll. Z.B. threads, sockets, sind einfach zu unterschidlich unter Windows/Unix/....



  • Ich versteh immer noch nicht wie ein Wrapper funktionieren soll.

    Wie sollen z.b. bei SOCKETS Windows funktionen auf Linux funktionieren o_O


  • Mod

    wrap schrieb:

    Ich versteh immer noch nicht wie ein Wrapper funktionieren soll.

    Wie sollen z.b. bei SOCKETS Windows funktionen auf Linux funktionieren o_O

    So:

    Wrapper Header

    void use_socket();
    

    Wrapper Quellcode:

    void use_socket()
    {
     #ifdef WINDOWS
      // Quellcode für Windows
     #elif defined(LINUX)
      // Quellcode für Linux
     #endif
    }
    

    Oder meinetwegen auch unterschiedliche Quelltextdateien für unterschiedliche Systeme

    Benutzer macht:

    #include<socket_wrapper.h>
    
    use_socket();
    


  • wrap schrieb:

    Ich versteh immer noch nicht wie ein Wrapper funktionieren soll.

    Wie sollen z.b. bei SOCKETS Windows funktionen auf Linux funktionieren o_O

    Ein Wrapper wird zur Schnittstellenanpassung benutzt:

    // gegeben sei die Funktion:
    int Find(int* array, int size, int value);
    
    // So will ich sie aber aufrufen:
    int FindWrapper(int val,  int sz, int* arr)
    {
      return Find(array, sz, val);
    }
    


  • Stefan schrieb:

    Ein Wrapper wird zur Schnittstellenanpassung benutzt:

    So pauschal nicht. Wenn du schreibst "wird auch zur Schnittstellenanpassung verwendet" ist das OK.
    Es kann durchaus sein, dass man auf verschiedenen Plattformen Funktionen mit gleicher Signatur hat, dann hat der Wrapper die gleiche Schnittstelle.



  • l'abra d'or schrieb:

    Es kann durchaus sein, dass man auf verschiedenen Plattformen Funktionen mit gleicher Signatur hat, dann hat der Wrapper die gleiche Schnittstelle.

    Und wofür schreibt man dann einen Wrapper (=Adapter, guck Dir mal das Adapter-Pattern und dessen Zweck an)? Wenn es nichts zu adaptieren gibt, weil schon alles passend ist, dann schreibt man keinen Adapter. Wozu auch?



  • Das Beispiel von SeppJ sieht für mich ja noch logisch und Sinnergebend aus.

    Aber wofür das hier ?
    Aus welchem Grund sollte man die Funktion Find so aufrufen ?
    FindWrapper(int val, int sz, int* arr);

    Ich sehe da kein Vorteil drin.

    int Find(int* array, int size, int value); 
    
    // So will ich sie aber aufrufen: 
    int FindWrapper(int val,  int sz, int* arr) 
    { 
      return Find(array, sz, val); 
    }
    


  • Stell Dir vor, Du hat ein Programm, das soll auf fünf verschiedenen Plattformen laufen. Windows, Linux, MacOS und Android z.B.
    Jede Plattform hat vielleicht eine find-Funktion, wobei sie sich nur geringfügig unterscheiden. In der Parameterreihenfolge z.B. Du müsstest jetzt Dein Programm jedes mal anpassen, und zwar an jeder Stelle die find benutzt. Jetzt kommt der Wrapper ins Spiel. Er wrappt die unterschiedlichen find-Funktionen und bietet ein einheitliches Interface. Jetzt musst Du nicht mehr ändern sondern kompilierst einfach nur noch für jede Plattform neu...



  • Stell dir vor du möchtest etwas bestimmtes erledigen und benötigst dafür eine bereits fertige Bibliothek, damit es möglichst plattformunabhängig und gut getestet ist. Du suchst im Internet und findest leider nur eine Bibliothek in C, aber nicht in C++.

    Die alte C Bibliothek ist zwar soweit genau das was du suchst, aber sie macht sehr viel mit free und malloc rum. Du bist also nicht dumm und bastelst dir um diese alten C-Funktionen einen Wrapper in Form einer Klasse.

    Diese Beispielklasse ist sehr vereinfacht (kein Zuweisungsoperator, ...).

    In der Realität würde man all diese Funktionen auch noch einbauen, da es sonst doch Speicherleaks gibt. Stichwort: Rule of the big three.

    Du hast also folgendes gebastelt:

    class Wrapper
    {
     private:
      CLib *lib;
    
     public:
      Wrapper() { lib = lib_init(); } // Lib initialisieren
      ~Wrapper() { lib_cleanup(&init); } // Lib freigeben
    
      std::string DoSomething() 
      { 
        char *cstr = lib_get_str(); // String anfordern (malloc!)
    
        std::string s = str;  // in std::string kopieren
    
        lib_free_str(cstr); // String freigeben (free)
    
        return s; // std::string zurückgeben. Alles easy.
      }
    };
    

    Du kannst nun diese Klasse ganz normal nutzen:

    Wrapper w;
    
    std::cout << w.DoSomething() << std::endl;
    

    Der Vorteil liegt darin, dass du dir um die Freigabe des Speichers nun keine Sorgen mehr machen musst. Die Wrapper-Klasse macht das alles für dich. Im Hintergrund arbeitet natürlich noch immer die alte C Bibliothek. Man merkt davon aber nichts mehr: Du hast den alten Code mit den Möglichkeiten die C++ bietet "eingewickelt".

    Solche Wrapper kann man für alle möglichen sachen schreiben. Immer dann, wenn man sich dadurch arbeitet und Probleme erspart.



  • Facade Pattern



  • Also ist so etwas ein Wrapper ?

    Angenommen ich hab eine Bibliothek mit dieser Funktion:

    hex_zahl_einlesen()
    {
            unsigned var = 0;
            scanf("%x" , &var );
            return var;
    }
    

    Diese Funktion ist ja jetzt in C geschrieben.

    Also baut man sich einen Wrapper wenn man diese in C++ nutzen will ?

    main.cpp

    #include <iostream>
    #include "wrap.h"
    using namespace std;
    
    int main()
    {
    unsigned zahl = 0;
    unsigned ret = 0;
    
    wrapper w;
    
    cout<<"Eingabe: ";
    
            ret = w.hex_zahl_einlesen();
            zahl = ret + 0x1;
    
    cout << hex << zahl << endl ;
    
    system("PAUSE");
    }
    

    wrapper.h

    #include <stdio.h>
    
    #ifndef WRAP_H
    #define WRAP_H
    
    class wrapper
    {
            public:
    		int hex_zahl_einlesen();
    
    };
    
    int wrapper :: hex_zahl_einlesen()
    {
            unsigned var = 0;
            scanf("%x" , &var );
    
            return var;
    }
    
    #endif
    

    Wäre das so richtig das man um die C Funktion dann einfach eine Klasse baut?



  • Nein, das ist kein Wrapper sondern eine Portierung nach C++. Außerdem ist das Beispiel auch etwas unsinnig, hier macht wrappen keinen Sinn. Verwende die C-Funktion direkt in C++, geht ja prblemlos. C++ heißt ja nicht "bitte alles mit Klassen".



  • Das würde dann Sinn machen, wenn die C Funktion z.B. Speicher reserviert den du freigeben musst. In dem Fall könnte man sich das Leben mit C++ einfacher machen.


Anmelden zum Antworten