从Qt到C#,通过COM组件达成跨语言跨平台链接,或者说从非托管到托管
写在前面
c#真的是一种非常蛋疼的语言,和别的语言兼容性差,界面开发效率也不是很高,但是胜在库功能强大,对windows的兼容好,编译快。但是托管的特性决定了它….就是会非常蛋疼。
这里说下托管与非托管。托管的意思就是指代码是放在.netframework上运行的。
换句话说,就是托管的代码理论上并不会编译成二进制文件,再让机器去读取你的机器指令,而是让你的代码去指挥.netframework去控制你的操作系统。c#的代码更多的看上去是在提供服务和接口,而不是真正意义上的代码,这也是托管的含义。
这就是c#蛋疼的地方。它很快,提供的接口也很多很方便,但是有两个致命问题。
1.它的粒度不够细。有时候提供了接口给你,那你只能去调用微软大爷的接口,但是实际上也许你并不需要这么多东西,只能使用微软提供的一些结构或者类,好的方面说,这可是微软程序员,虽然不说是世界上最懂程序员的人,但也算是最懂的一批了。坏的方面来说,他们Size和Count老是乱用,虽然你也知道正常有效的代码是不可能也没必要重写的,但是你就是会用着用着就不自觉地想有没有可能微软重新把这些基础的结构重写一遍。
2.它和非托管dll之间稀烂的兼容性。这也是这篇博客主要要写到,托管相当于是让代码跑在一个框架上,非托管则是让代码在机器上跑,这二者之间整整差了一层,其兼容性可想而知。当然你可能说我们有伟大的clr,当然如果你认同烂就是好这个观点,那么clr也是可以接受的了。
qt 与 c#的互操作
qt和c#的关系看我上一段文字也能明白了,不能说没啥关系,只能说毫不相干。那么我们的qt和c#有两个互操作方案,两种方案各有优劣,两种我都会写一下具体的操作方案
1.通过clr连接qt和c#
通过clr做中间层,连接qt和c#,这也是可以的,具体方案见下文
关于如何在C#中调用C++的DLL,以及如何在C++中调用C#的DLL
优点:编写简单,做法好理解
缺点:除了这两个优点全是缺点。1.这样做接口修改会很麻烦,一个地方修改就可能要涉及到多个连接的clr dll,项目小 包装还比较简单,但是如果多个dll之间交叉引用的话就可能导致一些意想不到的引用问题。
2.通过COM组件连接
当然我们有一个更好的方法,就是通过COM组件来实现。
首先我们要知道什么是COM组件:
COM component(COM组件)是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术。在COM构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成复杂的应用系统。由此带来的好处是多方面的:可以将系统中的组件用新的替换掉,以便随时进行系统的升级和定制;可以在多个应用系统中重复利用同一个组件;可以方便的将应用系统扩展到网络环境下;COM与语言,平台无关的特性使所有的程序员均可充分发挥自己的才智与专长编写组件模块。
说得简单一点,就是把一大堆的dll通过一套特定规范,把他们丢到整个系统环境里面去,然后我们需要的时候就可以通过指定的GUID、接口名称等去直接运行这个dll。
相当于是把dll们丢进了一个黑箱里面,我只需要知道我输入什么、会输出什么,就行,怎么实现的,或者内存分配等等我不用管,有点像.netframework的理念,但是兼容更简单,只需要编译出来的DLL满足他们的规范就可以注册了,Windows也提供了相关的接口。但是还是很傻逼的是.net的com组件只能用.net的方式注册,这个下面会写到。
ok,那么来说一下怎么进行COM组件的连接
1.这里我写了个demo来测试一下,为了模拟实际的环境,我们可以写两个c#的类,一个是直接被调用,需要做成com组件的c#类,姑且叫它ProcessNow类,一个是间接被调用,就是被ProcessNow引用的,无关的c# dll,姑且叫他Com_Test
Com_Test里面随便写什么都可以,只需要知道这个是被引用了的,为了模拟实际环境而存在的一个类,重要的是ProcessNow怎么写
详情可以见:https://blog.csdn.net/kingmax54212008/article/details/73604195
这里提一嘴注册,c# dll的com组件 注册并不像非托管的com组件注册那样简单,而是需要通过.net的工具去进行注册,也就是说.net托管的com组件也只能在有.netframework的情况下调用,否则 是会出问题的,也就是说不能通过regsvr32注册,而是需要通过.netframework进行,需要用到vs的那个工具,叫什么我忘了,具体需要看博客