8

-fno-rttiでコンパイルされた共有ライブラリからサブクラス化しようとしています。残念ながら、私のコードベースの他のライブラリには-frttiが必要です。その結果、スーパークラスにtypeinfo構造体がないため、リンクエラーが発生します。

通常のコンパイルで受け取ったエラー:

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

私がサブクラス化したいクラスは、libsysutilsのandroidクラスです(スペースのために少し切り取っています):

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;
};

私のスタブは次のようになります:

class MyClass: public NetlinkListener {

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

    int start();
    int stop();

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

MyClassのすべてのメソッドは(空のスタブとして)実装されます

共有ライブラリ-frttiをコンパイルできません。これを回避する方法はありますか?

4

2 に答える 2

5

1)単純なケースでは、インターフェイスのCラッパー(RTTIなしで構築)を作成するだけで済みます。次に、RTTI対応プログラムからの抽象Cタイプとして扱う場合は、RTTI対応プログラムでCインターフェイスを使用できます。

2) RTTIを無効にする非常に正当な理由がない限り(たとえば、例外を使用してはならないドメインで作業している場合など)、RTTIを使用してライブラリをコンパイルすることは、まさにあなたがすべきこと(またはベンダーの要求)です。カーネル、ドライバー、またはその他の例外のないゾーンとして、またはメモリが不足している場合)。

3)dynamic_cast、例外、typeid演算子、または問題の原因となるものを使用しないようにライブラリを変更し、RTTIを無効にして再構築します。1と同様に、プログラムの編成方法に応じて、これを別個の抽象化ライブラリーにすることができます。

4a)次のオプションは、オブジェクトの型情報を決して参照しないことです(たとえば、dynamic_castを実行したり、オブジェクトをスローしたりしないでください)。これは面倒な場合があります。これにより、参照される型情報のリンカーエラーが削除されます。

4b)内部クラスを作成するのが最も簡単な場合があります(オーバーライドする必要のあるメソッドがあり、rtti依存プログラムとインターフェイスする必要のあるタイプがあるとします)。libの型を継承し、必要なオーバーライドを実行する型(inner)を作成できますが、その後、他のクラス階層を介してコールバックします(他の階層はrttiを自由に使用できます)。これで、innerクラスの仮想エクスポートは、rttiが無効になっているTUに配置されます(それ以外の場合は、基本クラスのタイプ情報を暗黙的に参照するため)。次に、タイプ情報の依存関係を簡単に隔離し、例外などを使用する階層を構築できます。この階層では、そのinnerタイプを値として使用します。もちろん、それが機能する場合は、すべての実装が定義されています--ターゲットプラットフォーム用にRTTIとvtablesがどのように構成されているかを理解する必要があります(ABI参照を参照)。RTTIの省略でさえ、標準のC++からの逸脱です。シンボルが存在すると、vtableが適切に構築され、これらの機能なしでコンパイルされたベースの情報が入力されることを示す情報はありません。

とはいえ、1と2は安全なオプションであり、3はno-rttiプラットフォーム拡張のドメイン内(安全)であり、4はシステムがないか一部のシステムでのみ自由に機能するアプローチです。

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.
};
于 2013-03-05T00:30:53.113 に答える
0

渡すと、gccのドキュメントに従ってと機能-fno-rttiのみが無効になります。クラスを派生させ、問題なく仮想メソッドを使用できるはずです。dynamic_casttypeid

エラーは通常、関数を定義せずundefined reference to typeinfo for classに宣言した場合に表示されます。virtual

実際、私はAOSPであなたがやろうとしていることを正確に実行しているのを見て、それらのファイルとあなたが投稿したコードスニペットの間に違いは見つかりませんNetlinkHandler.hNetlinkHandler.cpp

于 2013-03-05T00:32:14.027 に答える