首页 > 其他分享 >【大型软件开发】浅谈大型Qt软件开发(四)动态链接库的宏冲突问题、COM组件开发的常见问题

【大型软件开发】浅谈大型Qt软件开发(四)动态链接库的宏冲突问题、COM组件开发的常见问题

时间:2023-02-10 20:35:40浏览次数:47  
标签:常见问题 定义 OBJECT 大型软件 编译 static 单例 IMPORT 浅谈

最近工作的时候有一个链接库的对接工作,在对接时发生了一些小问题,这篇FAQ是办公室写这个库的工程师戴工写的,这里记录一下:

一、编译工程时报链接错误“不允许dllimport静态数据成员的定义”

1.错误截图

image

2.错误原因分析

此错误是Q_OBJECT和Q_DECL_IMPORT宏共同作用时产生的结果。查询微软文档可知:静态数据成员无法在定义dllimport类的同一程序中指定定义。

image

这句话表明,导出类时,其静态成员不可被外部覆盖定义。举个例子,有导出类如下:

image

其中宏定义为:
image

根据微软关于dllimport的说明,类静态成员变量n不可被覆盖定义,即进行这样的操作

image

可以看到,对普通成员函数fun进行覆盖,仅仅发出了编译警告,但编译器并没有明确拒绝这种行为,但在对静态成员n进行覆盖定义时,编译器报错,拒绝了此行为。

回过头来看Q_OBJECT宏的定义:

image

发现静态成员staticMetaObject,根据QMAKE规则,QT编译时会对包含有Q_OBJECT宏的类进行一次moc工作,而moc_*.cpp中刚好拥有staticMetaObject的定义操作:

image

因此,Q_DECL_IMPORT(即dllimport)宏导出的类中包含了Q_OBJECT宏时,违反了编译器规则,因此无法完成编译。

3.修改策略

(1)修改导出类,如果导出类中含有Q_OBJECT宏,保留导出定义,去除导入定义;
(2)去除Q_DECL_IMPORT声明。由QT向导生成的宏声明文件中,有条件编译控制宏BUILD_STATIC,当工程中定义了该宏时,便可取消Q_DECL_IMPORT宏的导入声明;也可以不定义BUILD_STATIC宏,而是手动修改文件,去除Q_DECL_IMPORT宏。

image

(3)去除/注释Q_OBJECT宏。导入类时,可以在工程代码中将导入库头文件中的Q_OBJECT宏逐个注释。
image

(4)从工程中移除相关头文件。

image

二、创建dll导入类时报警告“QObject: Cannot create children for a parent that is in a different thread.”

1. 错误截图

2.错误原因分析

这可能是由于工程编译版本类型与链接库的类型不一致导致,比如工程当前为debug版本,但链接库编译生成版本为release

3.错误修改策略

将工程生成版本调整为与链接库版本一致

三、单例写法:

原先的单例写法比较简单,代码大概如下:

static Test&Test::Singleton(){
	static Test Instance;
	return Instance
}

这样的单例模式看上去还行,这个也是我之前常用的单例模式。但是这个在COM组件的开发中是不够安全的,原因也很简单~因为我们提交给COM组件的IDispatch是指针形式提交的,这个指针有可能会在外部被析构掉(只是提出一种可能,这里尚未测试和验证),所以这个单例模式是指针不安全的。

既然如此我们就需要修改一种比较好用且指针安全的单例模式。今天看了下小余的代码我感觉还挺好用的,拿过来抄一下:

static NetServer* NetServer::Singleton() {
	static QMutex mutext;
	static QSharedPointer<NetServer> inst;
	if (Q_UNLIKELY(!inst)) {
		if (!inst) {
			inst.reset(new NetServer());
		}
	}
	return inst.data();
}

这段代码就是用的QSharedPointer 智能指针对单例指针进行维护,这样只要主进程还在,这个单例的指针就会一直保存在QSharedPointer内,就不会被析构了,除非你自己提供了一个析构的方法。

标签:常见问题,定义,OBJECT,大型软件,编译,static,单例,IMPORT,浅谈
From: https://www.cnblogs.com/Leventure/p/17107739.html

相关文章

  • 如何利用人工智能改善医疗行业?浅谈ChatGpt在医疗元宇宙的应用
    随着技术的不断进步,广州华锐互动打造出了适合医疗行业的元宇宙,并且也在不断寻找更加高效的方法来改善患者的医疗体验。这里,广州华锐互动为大家介绍一种利用人工智能的方法:C......
  • 【LOLHunter】【亨特儿】常见问题
    欢迎使用LOLHunter亨特儿,本程序完全免费,仅供测试官方交流二群:654923469(最新)官方交流一群:523361798常见问题软件打不开?软件基于.Net6.0平台开发,请确认正确安装了......
  • linux常见问题排查
    查看用户账号#查看系统所有用户cut--delimiter:--fields1/etc/passwd或者cut-d:-f1/etc/passwd#查看拥有特殊权限的用户awk-F:'$3==0{print$1}'/et......
  • (一)浅谈人工智能:ChatGPT
     欢迎关注微信公众号专注于网络安全领域,跟踪漏洞动态,深耕互联网,做一个深谙攻防之道的公众号。同时涉足多个领域,是哲学,抑或是文学与艺术,关注金融市场,研究全......
  • 浅谈JS词法环境
    JavaScript词法环境本文主要讲解JS词法环境,我们将看到什么是词法环境,词法范围如何工作,函数内部的名称如何解析,内部属性,弄清楚词法环境利于我们理解闭包。让我们开始吧.........
  • 浅谈mybatis返回单一对象或对象列表的问题
    目录mybatis返回单一对象或对象列表一、说明二、代码测试UserMap.xml映射文件dao文件UserMap.java测试代码和结果文件mybatis返回的对象包含集合 mybatis......
  • node配置与常见问题
    配置源查看源npmconfiggetregistry配置源npmconfigsetregistryhttps://npm.taobao.orgdigitalenveloperoutines::unsupportednode.jsV17版本中最近发布的O......
  • 浅谈Pytest中的warning处理
    浅谈Pytest中的warning处理没有处理warning我们写一个简单的测试importpytestdeftest_demo():importwarningswarnings.warn('testwarn',DeprecationW......
  • Django关于站点管理Admin Site的常见问题解决方法
    1.改变django默认语言的方法?仅需添加’django.middleware.locale.LocaleMiddlewar’到MIDDLEWARE_CLASSES设置中,并确保它在’django.contrib.sessions.middleware.Session......
  • 浅谈容器
      >Collencttion分三大类List,Set,Queue(实现了很多多线程,任务装载,为线程池高并发做准备) >Map ......