c++ - 在基于 Qt 的库中选择性导出类成员

标签 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() 是私有(private)的(并且没有内联方法调用任何这些函数),因此不需要导出这些符号,因为它们将单独由库使用。另一方面,f()g() 是有资格导出的成员,因此它们被显式标记。

问题:Q_OBJECT 宏为 QObject 中的方法声明了几个虚拟方法重写,而这些方法不是 导出(因为宏将扩展为不包含LIB_SHAREDQ_DECL_EXPORT 的声明)。因此,客户端代码中的虚拟表将是不完整的。

(不)解决方案:LIB_SHARED应用于整个类,正如通常建议的那样:

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

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

问题:有什么办法可以达到预期的结果吗?我尝试对 Q_OBJECT 宏进行一些修改,但没有成功。

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

感谢任何帮助。

PS:请注意,除了这个问题是在 Qt 环境中出现之外,它还可能发生在使用宏扩展来生成声明的任何地方,如本例所示。

最佳答案

尝试使用 pimpl idiom 并仅导出公共(public)部分。例如:

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

并创建私有(private)类,放置所有私有(private)(不可导出)的东西:

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

public slots:
    void i();
}

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

关于c++ - 在基于 Qt 的库中选择性导出类成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9332996/

相关文章:

c - 使用Rundll32.exe执行DLL导出的函数

c# - 如何避免引用 DLL 的引用 DLL

c++ - 手动填充顶点结构实现对齐

c++ - Cin 坚持输入并错误读取

c++ - Qt OpenGL 更新非常慢

c++ - QMainWindow 没有显示

c++ - 用户注销/登录后创建托盘图标时出现罕见错误

Qt不透明颜色画笔?

c++ - 我可以(应该)将我的 DBClientConnection 用作全局变量吗?

delphi - 从delphiXE使用pchar参数调用delphi 2006 dll