Qt做大型软件开发技术选型Part2:Qt调用C#编写的COM组件

之前有提到过我们项目部现在正在用Qt重构一个大型软件,现在的情景是这样的:

原先的软件是通过一个C++(CLR)的主程序,调用各种用C#开发的模块和程序,从而实现各种各样的功能。几乎所有的模块需要用到底层功能(比如语音、视频广播等等)都是通过与主框架底层交换消息码的形式发送的。

原来的框架有两个问题,一是因为年代太久了,现在整个软件的代码和内容实在是太过于冗余,模块之间的功能很多都有较差,废弃代码多,维护困难,占用内存过大,C#界面开发复杂,启动慢,用户反馈体验不好等问题。在经过半年的修修补补之后,我们决定重新开发主程序框架,再到后续的所有模块内容。

既然我们决定重新开发主程序,当然不可能是直接一次到位,直接把整个项目全部重写,这是不现实,也不可能的。所以开发方案是先只开发底层,然后这个底层主程序要完全兼容之前的模块,然后随着后续开发一点点把久的模块舍弃掉,直到全部都是新开发的模块。

我们在各种技术选型之后,决定选择使用纯C++做为底层的框架开发,Qt作为模块插槽。Qt开发主程序有几个好处,一是C++开发,考虑到我们的应用场景主要是学校(极大可能会遇到公立学校),可能会在未来遇到类似麒麟这类的国产linux系统(大趋势),加上兼容、跨平台等面向未来的需求,C++就成为了我们这个场景下的不二之选。当然了也可能会使用Qt进行开发,毕竟之前框架推倒的原因还是二十几年的积累导致代码过度冗余了。

进程间通信方案:Qt调用C#编写的COM组件

之前有提到Qt调Qt的COM组件,现在我们为了兼容之前的C#模块,必须要考虑的就是这个Qt调用C#编写的COM组件问题。目前的方案是通过几个中间件,让框架去调几乎所有的教学模块,并与之进行交互。

先来写一个COM组件:

C#编写COM组件,首先注意要确定我们DLL和应用程序的位数。调用方的位数要大于等于COM组件的位数。比如我们的Qt程序是64位的,那么COM组件就可以使32位或者64位的。但是反过来,如果COM组件是64位的,那调用方就只能是64位的。为了考虑到硬件兼容(我们的产品有可能会装到一些很垃圾的设备上,也包括arm设备),所有的程序都应该保证在32位的目标设备上进行开发。

所以我的下文中,COM组件要保证是通过32位编译,应用程序也是在32位下编译。

根据网上的教程,我们知道首先我们要有一个这样的C#类库,自己新建一个就可以了
image

然后点开Properties,找到AssmblyInfo.cs,将这行设为true
image

然后定义一个接口,我们的类要继承这个接口,因为貌似C#中的所有方法和事件都是通过接口来暴露和执行的?尽量保证自己的方法在接口中已经保有
image

然后继承这个接口,我们就可以开始写类了,内容如下(注意我加的标签):

image

ok,这样写完了之后就可以把项目编译,编译之后获得一个dll。叫CS_DLL_COM.dll,我们在工具栏中找到VS x86本机工具命令提示符
image

通过regasm CS_DLL_COM.dll的方式将该COM组件注册到系统中去

这个时候你应该注册成功了,想检查注册结果可以在regedit中,HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ICS_DLL_COM这个目录如果存在,那么就说明注册成功了
image

Qt在调用方同上一篇文章Qt开发Active控件:如何使用ActiveQt Server开发大型软件的主框架里面有一个简单的COM组件调用实例,这里就不一一展开了。

总结:

1、有一个网上没有提到的点就是:要保证调用方的位数大于被调用方的,如果C#是编译的64位COM组件,而调用方的Qt程序是32位的,很有可能就会调用失败,这点需要注意。

2、还有就是注册的时候需要用VS x86(根据位数而定,如果是64位的就请用X64) 本机工具命令提示符 的regasm指令进行注册,regsvr32指令来注册C#的DLL是会出错的。