Класс подклассов из разделяемой библиотеки, скомпилированной с -fno-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'

Класс, который я хочу создать в подклассе, является классом Android в libsysutils (немного вырезано для пробела):

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. Есть ли способ обойти это?

8

Решение

1) Для простых случаев вы можете просто создать оболочку C интерфейса (построенную без RTTI). Затем вы можете использовать интерфейс C в программах с поддержкой RTTI, при условии, что вы рассматриваете их как абстрактные типы C из вашей программы с поддержкой RTTI.

2) Компиляция библиотеки с помощью RTTI — это именно то, что вы должен делать (или запрос поставщика), если только нет веских причин для отключения RTTI (например, вы работаете в домене, где исключение не должно использоваться, например, ядро, драйверы или другие зоны без исключений) — или там, где память стеснена).

3) Измените вашу библиотеку так, чтобы она не использовала dynamic_cast, исключения, оператор typeid или что-либо еще, что вызывает проблему, и перестройку с отключенным RTTI. Подобно 1, вы можете сделать это отдельной библиотекой абстракций, в зависимости от того, как организована программа.

4a) Следующий вариант — никогда не ссылаться на информацию о типе объекта (например, не динамически передавать и не бросать его), и это может быть проблемой. Это удалит ошибки компоновщика ссылочной информации типа.

4b) Может быть проще создать внутренний класс (предположим, что есть методы, которые вы должны переопределить, и есть типы, которые вы должны взаимодействовать с rtti-зависимыми программами). Вы можете создать тип (inner), который наследует тип своей библиотеки и выполняет необходимые переопределения, но затем перезванивает через некоторую другую иерархию классов (другая иерархия может свободно использовать rtti). Теперь inner Виртуальный экспорт класса помещается в TU с RTT отключен (потому что иначе он будет неявно ссылаться на информацию о типе своего базового класса). Затем вы можете легко изолировать информационную зависимость типа и построить иерархию, которая использует такие вещи, как исключения — эта иерархия использует inner введите в качестве значения. Конечно, если это работает, это все реализация определена — вам нужно понять, как RTTI и vtables структурированы для ваших целевых платформ (см. ссылки ABI). Даже упущение RTTI является отклонением от стандарта C ++. Нет информации о том, что присутствие символа приведет к правильному построению ваших vtables и информации о типе базы, которая была скомпилирована без этих функций.

Тем не менее, 1 и 2 являются вашими безопасными вариантами, 3 находится в домене расширения платформы no-rtti (безопасный), а 4 является подходом, который может свободно работать на некоторых или только на некоторых системах.

Иллюстрируя 4б

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

Другие решения

Переходя -fno-rtti отключает только dynamic_cast а также typeid функциональность согласно документации gcc. Вы должны иметь возможность получать классы и использовать виртуальные методы без каких-либо проблем.

undefined reference to typeinfo for class ошибка обычно появляется, если вы объявляете функцию как virtual без предоставления определения для этого.

На самом деле я вижу NetlinkHandler.h а также NetlinkHandler.cpp в AOSP делать именно то, что вы пытаетесь сделать, и я не вижу никакой разницы между этим файлом и фрагментами кода, которые вы разместили.

0

По вопросам рекламы [email protected]