Выборочный экспорт членов класса в библиотеке на основе Qt - PullRequest
2 голосов
/ 17 февраля 2012

В попытке оптимизировать двоичный файл динамической библиотеки на основе Qt я пытаюсь выборочно экспортировать ряд соответствующих методов из классов, которые наследуются от QObject и используйте moc для определения пользовательских сигналов и слотов, вместо того, чтобы экспортировать их полностью (все их элементы).Ниже приведен пример кода.

#ifdef LIB_BUILD
    #define LIB_SHARED Q_DECL_EXPORT
#else
    #define LIB_SHARED Q_DECL_IMPORT
#endif

class C: public QObject {
    Q_OBJECT

public:
    LIB_SHARED void f();
    /* ... */

public slots:
    LIB_SHARED void g();

private:
    void h();

private slots:
    void i();
};

Идея: , поскольку h() и i() являются частными (и никакой встроенный метод не вызывает ни одну из этих функций), в этом нет необходимости.экспортировать эти символы, так как они будут использоваться только библиотекой.С другой стороны, f() и g() являются членами, имеющими право на экспорт, поэтому они явно помечены для этого.

Проблема: макрос Q_OBJECT объявляет парувиртуального метода переопределяет методы в QObject, и эти методы не экспортируются (поскольку макрос будет расширяться до объявлений, не содержащих LIB_SHARED или Q_DECL_EXPORT).Таким образом, виртуальная таблица будет неполной в клиентском коде.

(не) решение: применить LIB_SHARED ко всему классу, как обычно предлагается:

class LIB_SHARED C: public QObject { /* ... */ };

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

Вопрос: Есть ли способ достичь желаемого результата?Я попытался немного поработать с макросом Q_OBJECT, но безуспешно.

Я надеюсь, что решение будет работать и в системах Linux (при условии, что по умолчанию видимость скрытых символов), поэтому файлы .defнепригодный.Хаки, тем не менее, приветствуются:)

Любая помощь приветствуется.

PS: Обратите внимание, что помимо этой проблемы, созданной в среде Qt, она может происходить везде, где используется расширение макроса длягенерировать объявления, как в этом случае.

1 Ответ

2 голосов
/ 24 февраля 2012

Попробуйте использовать идиому pimpl и экспортировать только открытую часть. Например:

class CPrivate;
class LIB_SHARED C: public QObject {
  Q_OBJECT
private: 
    CPrivate* m_private;
public:
    ...
};

И создайте приватный класс, в котором размещены все приватные (не экспортируемые) вещи:

class CPrivate : public QObject {
    Q_OBJECT
public:
    void h();

public slots:
    void i();
}

Затем инициализируйте и вызовите приватную реализацию из открытого класса.

...