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

Jon*_*n L 8 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'
Run Code Online (Sandbox Code Playgroud)

我想要子类的类是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;
};
Run Code Online (Sandbox Code Playgroud)

我的存根看起来像:

class MyClass: public NetlinkListener {

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

    int start();
    int stop();

protected:
    virtual void onEvent(NetlinkEvent *evt);
};
Run Code Online (Sandbox Code Playgroud)

MyClass中的所有方法都已实现(作为空存根)

我无法编译共享库-frtti.有什么方法可以解决这个问题吗?

jus*_*tin 5

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

2) 使用 RTTI 编译库正是您应该做的(或供应商的要求),除非有充分的理由禁用 RTTI(例如,您在不应使用异常的域中工作,例如作为内核、驱动程序或其他一些无例外区域 - 或内存紧张的地方)。

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

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

4b) 创建一个内部类可能是最简单的(假设有些方法你必须重写,有些类型你必须与依赖于 rtti 的程序接口)。您可以创建一个类型 ( inner),它从它们的 lib 类型继承并执行必要的覆盖,然后通过其他一些类层次结构回调(另一个层次结构可以自由使用 rtti)。现在inner类的虚拟导出被放置在禁用rtti 的 TU 中(因为否则它将隐式引用其基类的类型信息)。然后,您可以轻松隔离类型信息依赖性并构建使用异常等内容的层次结构——该层次结构使用该inner类型作为值。当然,如果可行,则所有实现都已定义-- 您需要了解 RTTI 和 vtables 是如何为您的目标平台构建的(请参阅 ABI 参考资料)。甚至省略 RTTI 也是与标准 C++ 的偏差。没有任何信息表明符号的存在将导致正确构建您的 vtables 和在没有这些功能的情况下编译的基础的类型信息。

也就是说,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.
};
Run Code Online (Sandbox Code Playgroud)