使用-fno-rtti编译的共享库中的子类

时间:2013-02-27 00:04:19

标签: c++ subclass rtti

我正在尝试从使用-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。有什么方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:4)

1)对于简单的情况,您可以只创建一个接口的C包装器(没有RTTI构建)。然后,您可以在启用RTTI的程序中使用C接口,前提是您从启用RTTI的程序中将它们视为抽象C类型。

2)使用RTTI编译库正是所做的(或供应商的请求),除非有一个非常好的理由要禁用RTTI(例如,你正在工作)不应使用异常的域,例如内核,驱动程序或其他一些无异常区域 - 或内存紧张的情况。)

3)更改您的库以不使用dynamic_cast,exception,typeid运算符或其他导致问题并在禁用RTTI时重建的内容。与1类似,您可以将其设置为单独的抽象库,具体取决于程序的组织方式。

4a)下一个选项是永远不会引用对象的类型信息(例如,不要动态播放或抛出它) - 这可能很痛苦。这将删除引用类型信息的链接器错误。

4b)创建内部类可能最简单(假设有必须覆盖的方法,并且有些类型必须与依赖于rtti的程序连接)。您可以创建一个继承自其lib类型的类型(inner)并执行必要的覆盖,然后通过其他类层次结构回调(另一个层次结构可以自由使用rtti)。现在inner类'虚拟导出放置在TU中,rtti 禁用(因为它将隐式引用其基类'类型信息)。然后,您可以轻松隔离类型信息依赖关系并构建一个使用异常之类的层次结构 - 此层次结构使用inner类型作为值。当然,如果有效,那么实现定义 - 你需要了解如何为你的目标平台构建RTTI和vtables(参见ABI refs)。即使省略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.
};

答案 1 :(得分:0)

根据gcc的文档,传递-fno-rtti仅会禁用dynamic_casttypeid功能。您应该能够派生类并使用虚方法而不会出现任何问题。

如果您将某个函数声明为undefined reference to typeinfo for class而未对其进行定义,则通常会出现virtual错误。

事实上,我在AOSP中看到NetlinkHandler.hNetlinkHandler.cpp正在执行您正在尝试执行的操作,但我发现这些文件与您发布的代码段之间没有任何区别。< / p>