在基于Qt的库中有选择地导出类成员

时间:2012-02-17 17:49:08

标签: c++ qt dll linker

为了优化基于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_SHAREDQ_DECL_EXPORT)的声明。因此,虚拟表在客户端代码中将是不完整的。

(联合国)解决方案:LIB_SHARED应用于整个班级,因为通常建议:

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

这解决了链接问题,但未达到主要目标(消除不必要的导出表条目),至少不是基于QObject的类。

问题:有没有办法达到预期效果?我试过在Q_OBJECT宏周围乱七八糟,没有成功。

我希望有一个适用于Linux系统的解决方案(假设默认隐藏符号可见性),因此.def文件不适用。然而,欢迎黑客:)

感谢任何帮助。

PS:请注意,除了这个问题是在Qt环境中构建的,它可能发生在使用宏扩展来生成声明的任何地方,就像在这种情况下一样。

1 个答案:

答案 0 :(得分:2)

尝试使用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();
}

然后从公共类初始化并调用私有实现。