问题描述
我试图从使用-fno-rtti编译的共享库子类化。不幸的是,我的代码库中的其他库需要-frtti。因此,我得到链接错误,因为超类没有typeinfo结构。
I am trying to subclass from a shared library which was compiled with -fno-rtti. Unfortunately other libraries in my code base require -frtti. As a result I am getting link errors because the superclass does not have a typeinfo struct.
在正常编译中收到错误:
Error received in a normal compilation:
out.o: in function typeinfo for MyClass:myclass.cpp(.data.rel.ro.<cpp magic>): error: undefined reference to 'typeinfo for NetlinkListener'
我想要子类的类是libsysutils中的android类:
The class I want to subclass is an android class in libsysutils (snipped a little for space):
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中的所有方法都被实现(作为空存根)
All the methods in MyClass are implemented (as empty stubs)
我无法编译共享库-frtti。有没有办法解决这个问题?
I cannot compile the shared library -frtti. Is there any way to work around this?
推荐答案
1)对于简单的情况下,你可以创建一个C包装的接口(无RTTI构建)。
1) For simple cases, you could just create a C wrapper of the interface (built with no RTTI). Then you can use the C interface in RTTI enabled programs, provided you treat them as abstract C types from your RTTI enabled program.
2)使用RTTI编译库是完全相同的,因此你可以在RTTI启用的程序中使用C接口。您应该应该做什么(或供应商的请求),除非有一个很好的理由禁用RTTI(例如,您在一个域中不应该使用异常,例如内核,驱动程序或一些其他没有异常区域 - 或内存不足的情况下)。
2) Compiling the library with RTTI is exactly what you should do (or request of the vendor), unless there is a very good reason for RTTI to be disabled (e.g. you're working in a domain where exceptions should not be used, such as a kernel, drivers, or some other no exception zone -- or where memory is tight).
3)改变你的库不使用dynamic_cast,exception,typeid运算符,无论是什么,导致问题和重建与RTTI禁用。类似于1,你可以使它成为一个单独的抽象库,这取决于程序的组织方式。
3) Alter your library to not use dynamic_cast, exceptions, typeid operator, or whatever it is that causes the issue and rebuild with RTTI disabled. Similar to 1, you can make this a separate abstraction library, depending on how the program is organized.
4a)下一个选项是永远不要引用类型信息对象(例如不要dynamic_cast或抛出它) - 这可以是一个痛苦。这将删除引用类型信息的链接器错误。
4a) The next option is to never reference the type info for the object (e.g. do not dynamic_cast or throw it) -- and this can be a pain. That will remove linker errors of referenced type infos.
4b)最简单的方法是创建一个内部类(假设有一些方法必须重载,必须与您的rtti相关程序接口)。您可以创建一个类型( inner
),该类型继承自其lib类型并执行必要的覆盖,然后通过其他类层次结构(其他层次结构可以自由使用rtti)。现在, inner
class'virtual exports放置在一个有rtti disabled的TU中,因为它会隐式引用其基类的类型信息。然后你可以很容易地隔离类型信息依赖,并建立一个使用异常的层次结构 - 这个层次结构使用 inner
类型作为一个值。当然,如果有效,都是实现定义 - 您需要了解RTTI和vtables如何结构化为您的目标平台(见ABI参考)。即使省略RTTI也是偏离标准C ++。没有信息表明符号的存在将导致你的vtables的正确构造和类型信息的一个基地,编译没有这些功能。
4b) It may be easiest to create an inner class (suppose there are methods you must override, and there are types you must interface with your rtti-dependent programs). You can create a type (inner
) which inherits from their lib's type and performs the necessary overrides, but then calls back through some other class hierarchy (the other hierarchy is free to use rtti). Now the inner
class' virtual exports are placed in a TU with rtti disabled (because it will otherwise implicitly reference its base class' type info). Then you can easily quarantine the type info dependence and build out a hierarchy which uses things like exceptions -- this hierarchy uses that inner
type as a value. Of course, if that works, it's all implementation defined -- you would need to understand how RTTI and vtables are structured for your targeted platforms (see ABI refs). Even omission of RTTI is deviation from standard C++. There is no information that states that the presence of a symbol will result in proper construction of your vtables and type info of a base which was compiled without those features.
,1和2是您的安全选项,3是在no-rtti平台扩展(安全)的域内,4是一种可以在没有或只有某些系统上工作的方法。
That said, 1 and 2 are your safe options, 3 is within the domain of the no-rtti platform extension (safe), and 4 is an approach which is free to work on no or only some systems.
说明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.
};
这篇关于使用-fno-rtti编译的共享库中的子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!