8 votes

Sous-classement d'une classe de la bibliothèque partagée compilée avec -fno-rtti

J'essaie de créer une sous-classe à partir d'une bibliothèque partagée qui a été compilée avec -fno-rtti. Malheureusement, d'autres bibliothèques dans ma base de code nécessitent -frtti. Par conséquent, je reçois des erreurs de liaison parce que la superclasse n'a pas de structure typeinfo.

Erreur reçue lors d'une compilation normale :

out.o: in function typeinfo for MyClass:myclass.cpp(.data.rel.ro.<cpp magic>): error: undefined reference to 'typeinfo for NetlinkListener'

La classe que je veux sous-classer est une classe Android dans libsysutils (coupée un peu pour des raisons de place) :

class NetlinkListener : public SocketListener {
    char mBuffer[64 * 1024];
    int mFormat;

public:
    static const int NETLINK_FORMAT_ASCII = 0;
    static const int NETLINK_FORMAT_BINARY = 1;

    NetlinkListener(int socket);
    NetlinkListener(int socket, int format);
    virtual ~NetlinkListener() {}

protected:
    virtual bool onDataAvailable(SocketClient *cli);
    virtual void onEvent(NetlinkEvent *evt) = 0;
};

Mon talon se présente comme suit :

class MyClass: public NetlinkListener {

public:
    MyClass();
    virtual ~MyClass();

    int start();
    int stop();

protected:
    virtual void onEvent(NetlinkEvent *evt);
};

Toutes les méthodes de MyClass sont implémentées (en tant que stubs vides)

Je ne peux pas compiler la bibliothèque partagée -frtti. Existe-t-il un moyen de contourner ce problème ?

5voto

justin Points 72871

1) Pour les cas simples, vous pouvez simplement créer un wrapper C de l'interface (construit sans RTTI). Vous pouvez alors utiliser l'interface C dans les programmes compatibles avec la RTTI, à condition de les traiter comme des types C abstraits à partir de votre programme compatible avec la RTTI.

2) La compilation de la bibliothèque avec RTTI est exactement ce que vous devrait (ou à la demande du vendeur), à moins qu'il y ait une très bonne raison de désactiver le RTTI (par exemple, vous travaillez dans un domaine où les exceptions ne devraient pas être utilisées, comme un noyau, des pilotes, ou une autre zone sans exception -- ou lorsque la mémoire est restreinte).

3) Modifiez votre bibliothèque pour ne pas utiliser dynamic_cast, les exceptions, l'opérateur typeid, ou tout ce qui cause le problème et reconstruisez avec RTTI désactivé. Comme pour le point 1, vous pouvez en faire une bibliothèque d'abstraction séparée, en fonction de la façon dont le programme est organisé.

4a) L'option suivante est de ne jamais référencer l'information de type pour l'objet (par exemple, ne pas faire de dynamic_cast ou ne pas le lancer) -- et cela peut être pénible. Cela supprimera les erreurs du linker concernant les informations de type référencées.

4b) Il peut être plus facile de créer une classe interne (supposons qu'il y ait des méthodes que vous devez surcharger, et qu'il y ait des types que vous devez interfacer avec vos programmes dépendants de la rtti). Vous pouvez créer un type ( inner ) qui hérite du type de leur lib et effectue les surcharges nécessaires, mais rappelle ensuite à travers une autre hiérarchie de classes (l'autre hiérarchie est libre d'utiliser rtti). Aujourd'hui, le inner Les exportations virtuelles de la classe sont placées dans une UT avec rtti handicapé (car sinon, il fera implicitement référence aux informations de type de sa classe de base). Ensuite, vous pouvez facilement mettre en quarantaine la dépendance de l'information de type et construire une hiérarchie qui utilise des choses comme les exceptions -- cette hiérarchie utilise cela inner comme valeur. Bien entendu, si qui fonctionne, c'est tout la mise en œuvre définie -- Vous devez comprendre comment RTTI et vtables sont structurés pour les plates-formes que vous ciblez (voir les références ABI). Même l'omission de RTTI est une déviation par rapport au C++ standard. Il n'existe aucune information indiquant que la présence d'un symbole entraînera une construction correcte de vos tables virtuelles et des informations de type d'une base qui a été compilée sans ces caractéristiques.

Cela dit, les points 1 et 2 sont des options sûres, le point 3 relève de l'extension de la plate-forme no-rtti (sûre) et le point 4 est une approche qui est libre de fonctionner sur aucun système ou sur certains systèmes seulement.

Illustration 4b

class MyClass // << cast me. throw/catch me. get my mangled name,
              //    but put my family's virtual exports in a TU with RTTI enabled
: public MyRTTIEnabledFamily {
public:
    MyClass() : d_inner(*this) {}
    virtual ~MyClass();
private:
    void cb_onEvent(NetlinkEvent * evt) {
        // no-rtti suggests exceptions may not be available,
        // so you should be careful if your program throws.
        someInfo = evt->getInfo();
    }
private:
    // non-rtti hierarchy
    class t_inner : public NetlinkListener {
    public:
        t_inner(MyClass& pMyClass) : NetlinkListener(), d_myClass(pMyClass) {
        }

        virtual ~t_inner(); // << put your virtual exports in a TU with RTTI disabled.
                            //    one out of line virtual definition is necessary for most compilers
    private:
        virtual void onEvent(NetlinkEvent * evt) {
            // how the callback to your imp actually happens
            this->d_myClass.cb_onEvent(evt);
        }
    private:
        MyClass& d_myClass;
    };
private:
    t_inner d_inner; // << don't do anything with my type info -- it does not exist.
};

0voto

Tuxdude Points 8652

Passage -fno-rtti ne désactive que l'option dynamic_cast y typeid conformément à la documentation de gcc. Vous devriez pouvoir dériver des classes et utiliser des méthodes virtuelles sans problème.

Les undefined reference to typeinfo for class L'erreur apparaît généralement si vous déclarez une fonction comme virtual sans en donner la définition.

En fait, je vois NetlinkHandler.h y NetlinkHandler.cpp dans l'AOSP faisant exactement ce que vous essayez de faire et je ne trouve aucune différence entre ces fichiers et les extraits de code que vous avez postés.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X