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