In an effort to optimize the binary of a Qt-based dynamic library, I’m attempting to selectively export a number of relevant methods from classes that inherit from QObject and use moc to define custom signals and slots, instead of exporting them entirely (all of their members). Some sample code is below.
#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();
};
The idea: since h() and i() are private (and no inline method call any of these functions), there is no need to export these symbols, since they will be used by the library alone. On the other hand, f() and g() are members eligible for exporting, so they’re explicitly marked for that.
The problem: the Q_OBJECT macro declares a couple of virtual method overrides for methods in QObject, and these methods are not exported (since the macro will expand to declarations not containing LIB_SHARED or Q_DECL_EXPORT). Thus, the virtual table will be incomplete in client code.
The (un)solution: apply LIB_SHARED to the entire class, as it is typically suggested:
class LIB_SHARED C: public QObject { /* ... */ };
This solves linking problems, but the primary goal (eliminating unnecessary export table entries) is not reached, at least not for QObject-based classes.
The question: is there any way to achieve the desired result? I’ve tried messing a bit around the Q_OBJECT macro, with no success.
I hope for a solution that works on Linux systems too (assuming hidden symbol visibility as default), so .def files are not applicable. Hacks, however, are welcome 🙂
Any help is appreciated.
PS: Note that besides this problem is framed in a Qt environment, it can happen anywhere where a macro expansion is used to generate declarations, as in this case.
Try to use pimpl idiom and export only public part. For example:
And create private class where placed all private (non exportable) stuff:
Then initialize and call private implementation from public class.