现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

VS2015的跨平台特性会对Qt带来冲击吗

2015-07-13 19:48 工业·编程 ⁄ 共 18108字 ⁄ 字号 暂无评论

vs2015支持c++开发跨平台的库,这样对于Qt而言会有多大的冲击呢?将来用VS开发c++跨平台和QT开发跨平台应用发展趋势各是怎样的?如果现在新项目要开发跨平台的高性能应用,如果用c++是选择QT还是VS2015的跨平台特性呢?另外VS2015跨平台对于界面的支持如何?

注意:不是在讨论IDE,也不是在讨论.net的跨平台!而是VS支持c++跨平台的特性。既然要跨平台,对于与系统无关的库显然是用标准c++。而涉及到与系统相关的API的封装,VS2015(姑且就用IDE来代称)会向Qt一样去封装成统一的API吗?或者说会去走Qt的路吗?

各抒己见:

VS 2015 是个庞然大物,有多大呢?大家可以去它的下载页围观一下:Visual Studio 2015 CTPs

但细到楼主的这个问题,其实 VS 的跨平台特性的重点还是手机 app 的开发,而且只是在一个 IDE 里开发。而不是一份代码跨多个平台。至少从 Build cross-platform apps with Visual C++ 这篇文档我是这么理解的。我没有时间做的更细。如果题主了解 Qt 手机应用的开发,再下载一下 VS 2015 做个测评,就完全可以得出一个简单的结论,根本不用提问。微软的这个特性,野心很大,希望是能一举拿下 iOS 和 Android 平台手机应用的开发。

不过我连这个也不看好。但我的原因很主观:

经过了这么多年的发展,软件开发行业已经完全渗入了整个社会。当年的那种,比如说五笔吧,一个软件只要是用电脑的都会用到,这种可能性已经非常小了。一个软件解决方案的针对性是非常强的。而它的应用场景的复杂已经远远超过一般人的想象。想打造一套方案,或者时髦一点,生态环境,拿下整个市场,从HPC集群到PC再到手机,甚至路由这样的嵌入式设备?面对这个想法,我只能呵呵了。而微软就觉得这是可行的。更简单地说,在前所未有的细分下,针对一个特定的任务,从开发环境,工具链,到所选择的语言都会非常地不同,这不是一个 VS 就可以满足的。

以上是我个人觉得 VS 2015 实在是托大的理由。下面说说我对 Qt 的认识。

Qt 最早是用来实现 UI 的跨平台库,最早如果你先在 Unix 实现了一个程序,然后想移植到 Windows 上,那是要买 License 才行的,这也是早期 Qt 的主要收入来源。之后 Qt 逐渐移植到了苹果上,后来被诺记收了又可以在 S60 上跑。再后来被诺记卖了,于是支持 Android 。尽管最近的金主都是在希望 Qt 可以跑手机。但 Qt 最大的用户在 KDE 上,由于它是 Linux 甚至整个类 Unix 上环境不多的可用的 GUI 程序开发框架和环境,至少一大半跑在 Unix-like 下的 GUI 程序都会用到 Qt (另外一半是 Gnome, 还有一点点是其它,……)。这部分开发者才是 Qt 整个社区的基石,而他们尽管在产品的理念上会跟风微软和苹果,但他们是不会在短时间内转向 VS 的,更长时间看也不会。

当然 Qt 最近有点火,不光是国内,根据我的见识,那是因为做特定的嵌入式开发的缘故,做手机应用开发有,但并不算常见。所以, VS 就算在手机应用开发上火起来,对于 Qt 来说仍不是什么大不了的事情。只是在短期内损失一批潜在的贡献者而已。当然,上面可以看出,我对 VS 这玩意可以成功也持保留意见。

所以简单地说, VS 2015 这东西目前跟 Qt 风马牛不相及,自然也没什么冲击可言。

最后补充一下:

我觉得题主的这个提问没有提到点子上。因为 VS 说到底还是 IDE ,而 Qt 是开发框架。两者没有什么可比性。如果仅仅针对这个跨平台的特性而言。 VS 的这个方案跟没法与 Qt 相提并论,尽管我也不看好 Qt 程序的跨平台,所以 VS 2015 的这个特性根本就没有什么亮点可言。

更进一步推,题主的提问,可能只是初学者,想选一个简单的跨平台的开发环境做学习之用。我觉得还是 Qt 吧。原因很简单, Qt 环境比 VS 小得多,目标也确定的多。如果想赚钱,请直接去投苹果。 当然安卓也是一个选项。 VS 看上去嘛都有,什么都可以干,但是用上了,我估计会有种,这玩意怎么做嘛嘛不行的感觉。如果题主是重度 VS 使用者的话另说。

先说下个人观点,我不看好Qt。

“相对客观”的说:

1)Qt 在iOS和Android的UI支持上只能算是一般,和原生UI相差甚远,对平台新版本的新特性支持薄弱。VS对这方面的支持,基于乔布斯的评语“微软太缺乏审美能力”,我也表示完全不看好。

2)业务层用Qt的库相比个家公司自己用原生的C艹库差别还有的。除非是哪家公司用Qt做了基础库,这是例外。基于VS的iOS、Android支持的编译器是gcc和clang,WinRT是MSVC,这部分和Qt都是一致的。

3)Qt的反射封装或者是Meta系统封装很重,至少要超过了c艹标准的rtti。虽然这套系统适合用来开发UI,但是作为业务层,如此重的外壳,用Qt就失去了一部分用java、objective c 迁移到C艹的性能优势。VS里面由于编译链的限制,而且基于llvm的coreclr支持还是幼儿期,几乎不用考虑c#的可能性。

4)最近几个月都在观察QtBug 列表,上面用户Qt对iOS、Android吐槽不断,小Bug层出不穷,甚至有的会影响正常启动。对WinRT的支持更不给力。VS对WinRT支持肯定会是Native的,至于其他两个平台,得靠自己维护了。

5)Retina支持。除了Mac平台支持稳定,其他平台只是承诺要增加支持。那个Improve Retina 支持的帖子是去年发的,今年年初发布的Qt5.4也只是完善了Mac部分和加入实验性质的Windows、Linux支持。等到完美加入这部分支持,又是何年何月?

6)Qt对移动端的投入究竟能有几斤几两?首先说一个不相干的话题是,Qt对桌面跨平台的支持可谓是筋疲力竭:对Windows 8/8.1的2xDPI显示支持(HIDPI),还需要手动设置环境变量外加程序内启动选项选项才能开启,不然用Qt原始方式实现的界面都是变形扭曲的;Mac的StatusBar 中用设置了template的NSImage 何年才能有;Linux在从Qt5.1就regression消失的TrayIcon也是时隔三个大版本到即将发布的Qt 5.4.2才有修复。其6个月的漫长的开发周期,庞大而臃肿的库,面对对更新迭代更疯狂的移动端,Qt的表现是Qt缺乏有对iOS、Android的相关支持,运行时家常便饭的各色crash,对WinRT的支持我认为这更象是一个hacker的项目。VS只有等VS2015才能评论。

7)我认为跨平台的C艹支持最显著的收益,是UI层封装一次跨平台的组件还是业务层的代码复用和性能优化?同1)3)6)中讨论,我个人认为Qt UI层的剥离平台相关的开发纯属扯淡,跨平台对C艹开放最大的收益还是复用高质量的基础库和核心业务代码带来的性能优势和项目维护优势。

8)Qt的Mobile开发支持,本身的开发工具是平台相关的,就是说Qt不能在Windows下开发iOS和Android,Qt也不能在Linux下开发iOS。相比Windows下VS2015 带来CrossMobilePlatform支持,开发机器只要是Windows就可以。这点上Qt编译链技术完败。

总而言之,跨平台的移动端开发的看点会是在业务层的开发上,UI层不应该是跨平台移动端开发争夺的重点。至于是VS 还是Qt,看官自己决定吧。

1. Qt SDK现在最新版本为5.4,按照官方说法,其LGPL协议下,提供以下目标平台的二进制开发包:

Windows Desktop x86/64

Windows Store App

Windows Phone 8.1

Android arm5/7

Android x86

MacOS

iOS

如果在GPL协议下或者之前老版本的Qt,可以支持塞班、黑莓、各种嵌入式开发板等平台。Qt支持的目标平台肯定还是比VS2015多的。

2. Qt不仅仅是一个c++界面库,它在实现了一套基于C++的反射功能的基础上,包含了网络、数据库、多媒体、测试框架、国际化工具、打包部署模块等,甚至还自己封装了一个WebKit模块。此外,Qt有收费才能使用的模块:

Qt Purchasing

Qt Charts

Qt Virtual Keyboard

Qt Data Visualization

现在,除了这些传统客户端开发工具以外,Qt也推出了云服务QtCloudServices。当然现在可能有变化。

3. 由于平台众多,Qt传统的基于QWidget界面在适配各种不同DPI的屏幕时,设计风格、控件及字体、图标大小等方面是会存在问题的,Qt5.4版本开始,官方宣称解决了DPI的问题:

High-DPI support for Windows and OS X

当然Qt5.4版本以前(包括现在),Qt官方希望大家使用QtQuick(QML,一种基于JavaScript的语言。c++与QML的关系,有点像C#与WPF一样)来解决触屏和DPI的问题,使用QML开发的话,在各个目标平台显示效果都是一样的,并且能够很方便的与C++代码交互。当然,与.Net的WPF比起来,还差很远,但毕竟跨的平台比WPF多。Qt官方有一个用来显示股市信息的QML Demo(http://doc.qt.io/qt-5/qtquick-demos-stocqt-example.html),在Win8、Android、WP上面显示效果都非常好。

4. QtCreator这个IDE与Qt配合起来非常完美,在VS里面使用Qt总感觉怪怪的。如果不使用Qt,由于C++语法过于复杂,VS这种宇宙级的IDE也不能像c#那样来IntelliSense C++,但无论如何还是要强于Qt Creator的

5. VS2015中C++的跨平台,肯定不会是一次编写处处运行(除非写的是标准C++)。如果带有界面(Win的MFC、WTL,Linux的X11)、或者有用到POSIX、WIN API,怎么可能不修改代码直接跨平台?而Qt有自己的一套GUI、Networks等框架,如果严格使用Qt SDK的标准来开发,完全可以不修改代码,在各个平台编译就行。

别用微软的东西。商业目的性太强,千万别被微软牵着鼻子走,血淋淋的教训。微软推出的垃圾多了去了。它什么都想做,很多都没做好:

1. MFC:Win31时代出生,Win95、98时壮大,虽然一直在更新,但是接口和概念都太老气。你要做现代界面,大量东西要自己手工去弄。同一个界面,一个熟悉MFC的程序员需要开发2周,而一个刚刚学习 Qt一个月的大学生,三天就搞定了。

2. WTL:好几个百万 DAU量级产品都试用过,最后都放弃没用了,微软也不怎么管了。

3. SilverLight:对抗 Flash,当年刚推出的时候,被微软碰成下一代桌面/web的统一解决方案,有的人真的去用了,结果呢?傻逼了。想找点第三方控件,少的要死,想招人也招不到,最后切换会flash去。

4. ASP•Net:当年微软到高校里面忽悠大学生学,学了半天,就业了,发现网页全部是 linux下的解决方案,傻逼了。一线的互联网公司就没有使用 SqlServer+ASP•Net的,都是清一色开源免费。

5. C#:这个还算好的了,十多年前照样当年骗着大学生学,说是比 java好很多。我很多年收到的学生简历都是精通C#,问题是十多年都过去了,看看今天的 TIOBE排行榜,java的分值是 c#的 4倍以上,服务端开发web/非web,企业级开发,java都是完爆 c#,更别说java开发 android设备的app了。微软的话再次没算数,当年学了很长时间 c#的学生,工作后碰都不会碰一下。

6. XNA:笑话一个,当年搞了好多 XNA游戏开发大赛,告诉大家 XNA就是游戏开发的明天,可以快速搭建小型游戏,或者快速编写游戏demo供验证。我们在评估使用什么给新人做 Demo用,最后评估下来,Python+Panda3D,易用性比 xna强几条街呀。

7. DirectMusic+DirectInput+DirectPlay:全都傻逼了。

8. 声音方面: Wave接口 -> DSound接口 -> CoreAudio接口,它就稳定不下来的。

---------------------------------------------------

微软的思路就是看着一个开发工具好,然后自己也要搞一套,然后借着自己强大的影响力,哄骗所有人来用他们的东西,最后大家用下来还是觉得开源的好。

微软的界面解决方案:GDI/Win32自己画,MFC/GDI自己画,基于Win32的各种界面库,WPF,SilverLight,Direct2D,看得你都不知道选哪个,但是你要做现代流行界面的话,一个Qt直接秒杀他们所有。

再给你说个血淋淋的教训,公司的游戏当年用的dx8开发,开发了两年,内测时微软开始推所谓革命性的dx9了,但是微软强调说,dx9兼容dx8,但是dx9性能更好,而且今后不会再有dx8的大更新。好吧,先不管,游戏先上着,但是竞争对手的游戏马上声称,完美支持dx9,充分发挥dx9的xxxx,我擦,没办法,既然今后趋势是dx9,那就改,学起来也挺快的,不就是api嘛,改了三个月基本改完。但是碰到各种坑,各种文档上找不到答案,网上还没人遇到的坑(当年dx9比较新),前前后后折腾了1年半,游戏才算ok了。跑了没多久,这时微软的 dx10出来了,号称完美兼容dx9,但是dx9不会再有本质上的更新了,你们快学dx10吧,性能很好,等你学会了 dx11又来了。

试想你一个程序员,一大半的时间都在给微软交学费,值得么?人生有多少时间呀?这就叫做被微软牵着鼻子走。再回过头来看看 OpenGL,到现在为止,还在用着 1.2/2.0标准,ES 3.0刚出,这就叫做稳定。一旦被商业利益捆版你就傻逼了,.Net到现在好像都5.0了吧?

跨平台:

我之前对写一些客户端的代码,用很多 VC的特性是抱容忍态度的,毕竟每个程序员有自己熟悉的领域。在项目时间有限的情况下,让熟悉 Windows的程序员在用很多 VC Only的特性,如: DWORD, DibSection, CString, #pragma once 等东西也是可以容忍的,毕竟当年客户端一般都是 Windows。

后来客户端发生了变化,一份代码需要同时运行于多个平台。除了vc编译外,还需要gcc, clang编译。当我们一份代码需要同时运行在 win32, 移动平台和 flash(crossbridge) 中时,当年积累的这些 vc only的代码化了不少时间翻新成跨平台的代码了。尽管vc有 #pragma once这些还是比较先进的语法糖,但 gcc/clang没有的情况下,只能退而求其次。

通过这次翻新,今后客户端也跟服务端执行一样要求,清一色的跨平台,再也看不到任何vc only的代码了。所有项目去 vs化。

------------------------------------------------

答疑1:【商业目的性太强,给微软教学费这几句非常可笑,现在还想学一个东西保一辈子么,学什么不是学,网页游戏火,学Flash,手机来了学objectc,学android开发,游戏引擎变成了Cocos和unity3d,做网站后来流行PHP等等,这类例子太多了,楼mfc,vb,asp,这些当年都带来了很多就业机会,让人入了门,楼主主观情绪太强】

没错正式学了新的,才会抛弃微软的东西,比如学了 Qt才会抛弃 MFC/WPF,学了 php才会抛弃 asp,学了 java才会抛弃 c#,学了 flash才会抛弃 silverlight,学了 MySQL才会抛弃 SqlServer。然后你会发现,我当初干嘛学微软的那些东西呀,浪费我时间么?

当年很多人是靠mfc vb开发,那是因为没有更好的,今天有那么多的其他选择,mfc vb已经可以退居二线了。也正是因为有那么多平台需要应对,特别如果是C/C++程序员,才不能用太多CString这些只能在vs下跑,没法到android和服务端用gcc编译,没法到ios下用clang编译的代码。这叫去微软化。

再者如果你没得选,比如你用dx,那么你就受苦吧,它每隔两年出一代,搞那么多版本到底是一开始接口就没设计好需要不断重构呢?还是故意非要重新弄一套?当初出9我没记错的话就是为了推winxp的,只有xp能跑。而dx10又是为了推vista和win7,逼着你游戏要更好效果必须dx10,而你想玩好游戏的话你可能被迫升级你的操作系统。这就叫商业利益驱动。

反观其他平台开发,很多图形工作站用ogl,游戏主机用ogl,android用ogl,ios用ogl,mac用ogl,而ogl几十年到今天主要版本还是2.0,包括es2.0,这就叫没有商业利益驱动的情况。

如此类推,出一个新平台,有微软的 vs2015和 Qt,那么用Qt吧。

如果你觉得vs作为ide很好用的话,在没有更好替代的ide前,你可以用vs这个ide来写Qt代码嘛。这叫逐步去微软化。

-----------------------------------

更新:擦,本来只有一句话,推荐Qt,远离微软,有人追问,补充了点,有人又追问,又补充了点,然后出了趟门回来,感觉跟捅了马蜂窝一样。既然都说到微软了,那就接着展开一下。

问题的本源

微软就是战线太长了,忙着去主导各种标准,制订各种框架,这样的话,才能更好的夹带私货,用一个你必须用的东西推进另外一个他想让你用的东西,诸如dx和windows,诸如c#和 http://asp.net,而又因为主导了开发者,才能进一步主导用户,而主导了用户,大量的利润便会随之到来。在整个链条中,如果消费者没得选择,开发者也没得选择时,微软就能想卖啥就卖啥,完全基业长青了。出个新东西没关系,不符合我的利益我就不支持。如果新东西很有前途,那我自己搞一套,然后再把我的开发者和用户绑架过去。

到底哪一个方向会有前途呢?微软自己也说不清。到底哪个领域对今后的软件生态影响比较大呢?微软自己也道不明。只能朝着各种有苗头的地方去努力,以前技术领域比较窄,微软可以囊括整条产业链,编译器/IDE/框架,开发者基本可以躲在微软的圈子里不出来。后面各个技术领域蓬勃发展,分支越来越多,微软就有些力不从心了。但是战略依旧没变,任然试图去主导任何一个技术领域的标准。利用自己的影响力去忽悠各种开发者:“跟我来吧,有美好的明天”,但技术领域每天都在推陈出新,产生新的细分。为了主导更多的新领域,称霸完一个领域后,微软的重心并不是完善该领域,而是继续集中精力称霸其他新的领域。

对于支持期的技术,微软会利用自己强大的影响力进行各种捆版整合,告诉你:“新的革命又到来了,你准备好了么?”,告诉你:“用了它之后,你就什么都不愁了”,“XXX即将停止支持”,然后各种社区中,一堆mvp前扑后拥的进行推广:“XXX大法好,MS法力无边”;书店的柜台上,瞬间多出几十本红色封面黑色封面的宝典;CSDN的主页里,各种微软 TechED, 夏令营。很多人一看,我靠,全世界都在用,我再不用是不是就要被淘汰了呀?

完成支持后,微软进入绑架期,为了不让你用其他的东西,微软想尽一切你的需求,然后为满足你可能的一切需求,开始拼命的飙版本,来兼容各种各样的东西。很多人觉得这个东西好像挺强的,什么都能做,不用学其他了,微软就笑开花了,觉得可以绑架大家了,于是开始疯狂的用该技术夹带越来越多的私货,或者是新技术,或者是为了强迫其他人用另一个东西,为了兼容这些私货,继续飙版本,这就叫绑架。

等到你积累了越来越多的代码,或者成熟框架后,你突然发现,原来你能做的事情,就是只能在微软给你划定的一亩三分地里面不断的耕耘。想用它开发一个微软商业上不支持的东西?没门。依赖微软越久,做出选择的成本越来越高。这时会有两种结局,第一种,微软给你指出下一个革命的方向,你别无选择,斩断原有积累投入到下一个革命中。异或,微软觉得自己在这个领域江山稳固了,竞争对手都没了,不会再出什么幺蛾子了,于是彻底开始不思进取,你用着过时的技术干着急。

曾任微软副总裁的李开复回忆:“一个产品队伍一旦失去了假想敌,就会松懈,盖茨和鲍尔默也会撤回对它的投资和支持。比如说,微软IE击败网景之后,微软就降低了投资,致使它的浏览器多年没有再进步,直到又出现了‘火狐’这个敌人,才又开始振作。”火狐就是网景的“遗孤”。

微软的绑架

MFC就是一个很好的例子,当年同 VCL竞争时挺上进的,VCL一死,MFC也跟着死了,现代的界面系统都是 windowless直接绘制控件了,笨重的mfc还在基于系统控件。大量的onpaint自己做,人招不到不说,工作效率奇低,熟练的mfc工程师还比不过学习Qt一个月的学生开发效率高,你说我会选啥?mfc还需要各种奇巧淫技才能达到 qt的效果,弄那些技巧的人变动,项目就傻逼了,考虑到这一点,你说我又会选啥?最近两年界面开发又开始脚本化了,你会发现 Qt有各种支持脚本(除了内嵌支持 js的 QtScript外,还有 Python的 PyQt,还有 Lua)任你选择。核心代码C++,逻辑界面python,用过脚本开发UI的人都不会想用回C++写UI,因为界面逻辑脚本化可以提高至少两倍以上的生产力。微软的策略呢?想用脚本?没门,因为我不推脚本但是我推c#,所以你想方便的写高级界面?还是跟着我去弄 .net和wpf去吧,这就叫绑架。面对绑架你别无选择,开发者微软系的代码和经验积累越多,想离选择非微软的东西成本就越高,想不被微软绑架的代价就越大。

为啥有人愿意给 Qt脚本化而不愿意给微软的界面系统脚本化呢?并不是微软的技术就比不过Qt,而是大家唾弃微软的臭脾气,外加Qt是开源的,为它实现脚本各种方便。这里并不是说开源的东西就一定比微软的东西好,微软有很多领先的技术甩开源几条街,主要问题在于微软的封闭性。所以我的论点并不是一定要用开源,而是建议大家有选择的余地下,选择非微软技术,比如qt, flash这种。

死也要主导行业标准

为了引导行业标准,微软很多设计的很好的东西,各种音视频格式,还有最近的 HD Photo图片格式,比 jpg2000 和google的webp好多了。但是很多人由于微软的封闭不买微软的帐,很多框架和软件都直接支持webp了,也没几个人支持wdp,在这种情况下,我宁肯选择次一等级的 webp。

微软的出过很多标准性的东西,比如wmv, wma格式,当年挺先进的,微软也天天忽悠人去用这两个格式,但是由于封闭,最终失去支持,大家选择了更加开放的方案来代替,微软也就不思进取了,最终视频领域 现在是 h.264/265,音频领域是 he-aac v2。

微软又试图代替 pdf,引领该领域的标准,然后自己出了一个 xps。论技术,确实高于 pdf很多,但是没人用呀,没软件支持呀,连打印机都只支持扫描成pdf格式。所以我选择 pdf并不是因为 pdf技术比微软强,而是因为它不是微软的。而且我估计个两年出个 pdf2,xps也就跟 wmv一样进棺材了。

再比如 SilverLight,微软在没有太大把握的情况下硬推这个东西,就是因为怕c#由于满足不了RIA使得C#开发的开发者流失到微软以外去,为此 .Net还逼迫大家升了几个版本。可惜,大家都知道的,于是微软自己对它的支持都少了很多。

你说微软技术弱么?不弱。那为啥这些明显乱七八糟的东西微软都要硬撑着试图主导行业标准但是最终又主导不了呢?那是因为我们先前提到的微软战略,从几十年前到现在都从来没有变过,然而时代变了。

Win32 API

Win32 是系统层最稳定的接口,一切功能的基础。这么基础的东西,微软该化大力气持续发展对不对嘛?非也,随便举两个例子你就会发现其实它已经落后世界很多了。微软是任性的,觉得我提供的开发模型可以解决一切问题,为什么要参考其他操作系统改进呢?即便其他操作系统提供的功能很好,我也要给你挑挑刺。而按照微软一贯的规律,系统 API领域,我完全控制了,那么我改进的动力也就不那么强了,庶民们岂能妄自议论 Win32 API,更别说想提交改动 patch给我了。

线程同步:如果你写线程同步,你会发现 Win32 API缺很多关键的东西比如:条件变量,读写锁,这两个最基本的能够组合成其他任何同步模型的东西,微软直到 Vista的年代才提供支持(msdn Condition Variable),这就意味着,你如果用了,你将面临很难在 xp下跑的情况。你问微软 xp怎么办,微软说用 event去 wait嘛。你就奇怪了,event这么弱智的东西能代替条件变量么,为啥不再xp年代就支持了?

单次初始化:pthread_once,没错,windows下面由于缺少这个东西,你再做一个全局变量供你的接口访问时,你需要保证该变量只被初始化一次。即便多线程同时调用访问该变量的接口,也不会出现两次初始化的情况,pthread_once就是做这个事情的。直接把代码写成:if (inited == false) { init(); inited = true;} 线程又不安全,外面加一个 CriticalSection,那你又需要在更前面去 Init这个 CriticalSection,还要保证不会发生多次 Init,问题还是没解决。于是很多人在 Windows下的解决方案是,在全局变量声明一个类的静态实例,这样 main()之前,那个类的构造函数能够提前被调用,进而又引入了新的问题,及多个全局实例又会存在谁先谁后被构造的问题,你又得用恶心的 #pragma宏来解决,最后初始化代码一团乱麻。而如果微软提供 pthread_once类似方法,那或许这一切都会变的很清爽。

网络接口:用过 winsock接口的人都觉得简陋,你想实现高性能的网络服务,需要控制 TCP的大量细节参数,比如 TCP_NOPUSH, TCP_CORK, 还有 QUICKACK这些控制调整 TCP面向流量优化或者面向流速进行化的基本功能,winsock上看都看不到。更别说 Google的 TCP速率优化(Kernel 3.2.12收录的 Google patch)等现代功能了。即便是对比最基本最传统的 posix套接字,winsock的行为也是错乱的,比如 REUSEADDR,再比如 Win32下你监听一个 UDP端口,给远端发送 UDP数据包,如果远端没有监听该UDP端口,那么你服务端收到 icmp: port unreachable后,那个udp socket就彻底被 reset了,后续什么数据都读不进来,持续给你报 10054,搞笑吧。除非你创建udp套接字时做一大堆 *windows独有的* 专门的设置,否则vista之前,你都会被 10054。vista之前,默认情况下,客户端如果拒绝收服务端的 udp包的话,服务端的 udp套接字就用不了了,这是不是在搞笑么?还有各种基础功能限制,比如:缺乏poll支持(强迫你用iocp代替),select最多64个fd,没有 socketpair。当然,没有这些也可以写网络应用,但写惯 unix下的网络代码突然来 win下写,就会觉得这真是个玩具呀。

TLS:TLS有数量限制也不管了,但是线程本地存储这个东西是需要 destructor的,即我创建了一个本地存储来存一个对象,我可以设置一个 destructor函数指针,在线程退出时,这个函数会被自动调用到。比如你想实现一个 per-thread cache(比如类jemalloc的 arena),线程退出时能够被自动析构,这个最基本操作在 Win下却可以把你别扭死,原生TLS API没有这个支持,你又不想所有线程退出都要强迫使用者调用一下 destructor,那么你开一个线程监听所有线程?还是怎么招?看看 boost和 jemalloc这些在 win下的 destructor实现,你就会发现恶心的要死,就像要在一块工整的电路板上,焊接一根非常碍眼的飞线一样。

GDI/GDI+: GDI是牛逼的,出生早又承当了 GUI的基础工作,毕竟那么多年了,做成这样是无可厚非的。但是XP年代的 GDI+一出生就落后于时代。比同期的同一个级别的开源项目 Cairo(gtk后端,wine用来模拟gdi/gdi+的后端,webkit/mono后端)和 Quartz(OS X图形后端)来,GDI+除了速度卡外,图像质量差,功能简陋,不支持抗锯齿,对GDI的字体效果也并没有质的改进。所以 Windows下的应用软件,一直因为字体和图像质量受到诟病。直到后面的 Direct2D出来希望改进这个局面,也已经是好多年以后的事情了。大量兼容 xp的程序还在跑在 GDI/GDI+上。

( 问题有很多,以下省略若干字)

按微软的能力,想改进这些基础接口,应该不是难事。但基础接口的长期滞后,折射出的是该公司全胜时期的傲慢。

统治与分治

微软的接口设计向来是缺乏美感的,喜欢复杂化,喜欢什么东西都搅合在一起。什么叫做大一统?就是什么都能做,貌似很强大,一个东西能做的事情很多,开始是好的,但是随着时间的推移,耦合度高,各种盘根错节,一旦其中一个设计很 “巧妙”的东西过时了,那所有依赖它的东西将面临死亡。什么叫做分治?就是保证简单性和可拆分性,每个系统专心做好一件事情。一个不行,换掉即可,整个解决方案是由若干全部可以替换的子模块组成的,这叫分治。

Windows技术栈就是一个典型的大一统设计,他有很多很巧妙,依赖性很强的东西。比如,“一切都是窗口”,这个思想,从设计上来说就是有问题的。举个简单例子,WSAAsynSelect 用过的人都知道,这是一个网络接口,用来判断哪个套接字上有事件。但是却又要传一个窗口句柄过去,让窗口来接受网络事件,这就是一个很搞笑的例子。微软为什么这么设计呢?因为应用程序本身有一个消息循环了,就是窗口消息循环,但是如果处理网络的应用程序使用类似 unix poll的方法,去等待消息的话,窗口消息就得不到处理了。如果把poll放到一个线程里的话,那UI线程要找网络线程做点事情,那网络线程在 poll的等待周期中,如果没有新的网络数据过来,可能短时间内没办法理会 UI线程的请求。于是微软的解决方案,就是让网络层的事件合并到 UI的窗口事件中,这样就比较方便了,全部在窗口消息队列,你要把UI和网络放到一个线程也可以,两个线程也罢。这样把两个风马牛不相及的事情搅在了一起的:“巧妙” 设计在微软的技术栈里数不胜数。

合理的处理方法应该是啥?应该是继续使用 Poll,每次 poll可以设一个比较短的时间,并且可以被外面线程唤醒,这样就不会出现之前的问题了,两件事情不会搅在一起,这就叫可拆分性。结果呢,不关网络,大量的其他东西都和窗口搅起来了,等到 Windows程序要移植的时候,就会变得万分痛苦。有人说不是有 IOCP么?看看有多少一流的服务器支持 iocp?再说java可以把所有不同操作系统的异步事件模型封装成NIO,对 Windows对的 iocp却提供单独的接口,而且直到 7.0以后才有,微软总喜欢和全人类反着来。

缺乏审美的设计,才会导致 Win32 API被 GUI所束缚这样一种结果。这在其他系统对比来说,这时听都没听过的事情。这是设计上的偶合,还有商业上利益的选择。比如网页开发,C# 和 http://asp.net绑定太紧,http://asp.net和 iis绑定太紧,iis和 windows又绑定太紧。微软的东西才出来都是先进的,可封闭的微软不愿意同外面合作。你要用我先进的东西,你就一个系列都要用。最终全部都搅在一起了,风险是相当大的,系统就像一个吞噬了各种化学物的怪兽一般,蹒跚前行。

而所谓简单性和可拆分性的东西,是四处皆可替换的东西。比如你做 web开发,你选一门语言,python,语言就做好语言的事情。外部的网络框架,可以用 django,flask, web.py等等,接口可以用 fastcg / cgi / wsgi / uwsgi / apache_mod, 而外部的服务器,可以用 apache, nginx, lighthttpd。清晰的被分成:语言层、框架层、协议层、服务层 四个不同的层次,每个层次若干备选方案,互相兼容,web.py过时了,我换 flask,apache过时了,我换nginx。每个产品都专注做好自己的事情,并前后适配其他层次的方案,python出问题了,我换 ruby,换php,协议任然用 apache_mod或者 fastcgi。这就是分治,具备美感的设计。

这样的情况在微软的技术体系里很难出现,这些技术运行到windows下水土不服不说,微软自己就不让你选:你要写asp .net,那语言你就用 c#(vb比较小众),用了http://asp.net你就要用iis,而iis只能跑在 windows下。外部的人很难兼容进来,本来微软就不太愿意支持其他技术。那么好,一开始可能领先,但是随着时间推移,这么长的链条中间一环出问题,可能会导致其他的跟着他一起被人抛弃。

微软一方面出于商业考虑,生怕自己技术链中哪个环节被人替换,一方面有些接口设计充满耦合,考虑不周,导致后面大量的主动升级和被动升级,什么 ocx, com, atl, ole,dx1-7类似的东西都可以搞出那么多来折腾人,系统内核 GUI,网络、多媒体,大量的 API偶合在一起。最终简单的一个 Office和 Windows一样臃肿丑陋,这就叫缺乏美感的设计。

C#

C#是一门简洁优雅的好语言,是微软中比较少见有品味的设计,这是因为 C#之父 Anders就是来源于微软之外的 Borland。Anders 早年为 Borland 设计的 Turbo Pascal 和 Delphi 就以编译速度快,使用简单和功能强大受到大众的喜爱,所以在设计 C# 时融入了很多早年的审美观。C#语言层面上胜过 java不少。我经常边用边骂 java到9到10了,也没想着好好的学学 C# 的一些特性。Java 这么多年连个 get/set 都不抄一下,连个unsigned都不肯给我用用。用 C#写代码比 java流畅不少,但应用范围太窄呀,我没办法还得接着用 java呀,应用范围广呀。我用 java写的程序随便运行在几乎任何平台上,大量最新的开源成果可以直接应用。可怜的C#却被微软画了一个圈,死死的呆在圈里出不来。其实大家都是欢迎 C#的,不然也不会有 mono这个项目了,但 mono运行效率比 jvm低不少,比原生的 .Net运行时低很多,库也不全,实在难以承当大任。

除了部分人专门从事 C#的工作外,现在互联网企业,几乎很难看得到 C#的身影:做移动应用,用原生的 java和 objc。做服务端用 C++/java/各种动态脚本,做页面用 Js 页游用 Flash。做PC游戏用C++/脚本,没C#什么事情。移动游戏主要也在使用 C++/脚本(unity只是众多游戏开发引擎中一个单例未来是否被代替未知,XNA就是个玩具)。唯一只有微软的老本行PC桌面应用,没错,是C#,但是现在也面临诸多挑战: CEF(Chromium Embedded Framework)用js直接写Windows本地应用,如网易云音乐用CEF效果拔群;Qt系列+脚本(越来越多互联网公司在用,如Wps);自己C++UI库/脚本(例子太多了)。这些方案你或多或少都能挑出些问题来,但不可否认的是她们正从各个方向蚕食 C#的传统地盘。你可能说C#在客户端能做很多非 UI的事情(比数据库和网络还有图像),但 CEF/Qt 这些播放点流媒体、访问下网络、弄下图像或者请求下数据库同样很简单。现在 GUI开发的脚本化进程正在席卷各种桌面开发方案, js等脚本运行速度越来越快,C#速度上并不能体现出数量级的优势,而且基于泛型的脚本语言开发效率比原来高很多,同时这些解决方案全是跨平台的。而整个进程中 C# 被排除在外了,这才是 C#真正危机的地方。

DirectX

有人奇怪我为何喜欢 OpenGL,话说白了只有一个理由,它是开放的而且它不是微软的。如今很多人会说你看 d3d 接口不错,兼容性高,CPU占用低而且画面好。没错,但记心好点的同志们把时间拉长一点,Win95时代微软强推 DirectX而封锁 OpenGL很多系统调用的事情各位还记得到吧?那各位还记得到 DX才出来时烂成什么样子么?当时业内骂声一片,很多人看了眼接口就扔了,直到 DX5出来的时候,你稍不留神,还会把整个屏幕画花了,或者弄死机了。当年 OpenGL领先 DX不是一个量级。直到 DX8出来了,才算完善了一些。微软为了商业利益,把整个行业拖后了数年之久。直到2006年,很多 3A大作还是以 OpenGL为图形底层,不鸟微软的 D3D。

微软的技术架构,向来不太优雅,耦合度又高。Dx7以前,DirectDraw的表面和 D3D设备还有纹理搅在一起,DSound的坐标系统又可以和 D3D的坐标系统搅在一起。大量的数据结构被定义出来,一个矢量一个矩阵还要单独定义一下,不准我跨平台库用自己的定义么?你就不能用个数组么?你强大是强大,但是你耦合度实在太高了。一个环节更新,所有环节被迫更新,然后就飙版本的原因之一。DirectX的设计就是没有品味的,如果按照简单性和可拆分性的思路来重新考虑,Dx软件包中,应该隔的比较开才行,能不定义的对象和结构体,尽量不定义,用C原始的类型或者数组来接口,这样不会妨碍我外面灵活使用。然后游戏开发者靠一门胶水语言把这些独立模块根据需要粘合在一起,这样的方式是不是更清爽一些呀?

开放的东西能自我适应性,自我修正。Real Networks估计很多人还没忘记,当年的他开发的 RM / RMVB视频格式,因为压缩比高,同信噪比下码率能有更低的码率,画面质量更好,而赢得了广泛的支持。但是 RM / RMVB却是一个封闭的视频格式,虽然领先了业界数年之久,但是数年后即被开放的 H264所代替,H264虽然一开始接受度不高,但是数以万计的人在帮他完善。学院派今天发研究出一种更有效的宏块搜索方式,不出两个月工程界就跟进了。今天有人发现一个运动估计的改进,明天有人实现个更低延迟的缓存管理,或者提升下错误恢复能力。免费的 x264不论从延迟,性能,画质,码率都直接秒杀很多商业公司的编码器,ffmpeg又可以轻易的播放h.264视频。最终 Real Networks抱着它的 rm/rmvb一起进了坟墓,死前还不忘叫一句它正在开发 rmvb2,超越 h.265标准的编码格式,业内嗤之以鼻。视频领域的玩法已经变了,H.264通过不断发展,最终颠覆了RMVB的商业模式,这就是一项技术自我适应,自我修正的例子。

今天的 D3D就像当年的 RMVB,就算他用商业手段狠狠恶心了 OpenGL一把,导致后面 OGL数年发展不顺,但是老话说得好:理胜力为常,力胜理为变;一时之强弱在力,千古之胜负在理。随着 OpenGL新标准的不断完善,虽然暂时不能彻底抛弃 DX,但封闭的 Dx必然会随着微软 Windows 逐渐边缘化,这就叫得道多助失道寡助。

全世界玩一套,微软自己玩一套

还是因为微软最初的战略没有改变,导致全世界一套,微软自己玩一套;微软看不起开源界,开源界也不理微软。再次强调,并不是只有开源才好,而是这么多家公司里,只有微软一家试图自己从头到尾建立一套完整的技术体系,只有微软一家采取如此封闭的策略。然而早年微软可以罩住整条产业链,并且活的很爽,但是现在大量基于开源界的最新成果都和微软技术栈水土不服。

所以开发者会面临:依赖微软和不依赖微软两种选择。依赖微软,很容易和外界形成隔离。而不依赖微软,你得到的是满天下的选择。前者强调高度集成统一,后者强调可拆分替换。然而,世界潮流,浩浩荡荡,顺之者昌逆之者亡。

成也萧何,败也萧何

早年的微软,象一个潜伏在丛林里的猎手,利用自己操作系统的优势地位,寻找着产业链最高端的用户需求。一旦一项技术可以满足用户某种根本需要,微软就不惜牺牲眼前的现金流,来换取未来的行业领导地位和盈利。或快速收购,或恶意打压,或自家出一套,任何一个领域只要有新的东西出现,微软就试图去控制它,并绑架获出钱养活接受了微软标准的软件开发商让他们支持,出钱扶持低端的开发者让他们学习微软标准,于是巨大的利润,随之而来。

这样的战略,使微软茁壮成长,并成为接二连三的行业标准拥有者。然而这样的战略有一个致命的BUG,就是标准必须是与时俱进的,微软需要不断调整已有标准,否则越来越多的标准就会成为束缚住微软的一条条绳索,越来越多的兼容性问题象一座座大山一样压得微软喘不过气来。掌握的标准越多,微软越难改变,随着时间的推移,将会被微软体系外更加迎合用户偏好的竞争者们所取代。

有人说:“微软错过了移动化浪潮,错过了云计算,是因为鲍尔默的误判。智者千虑必有一失,再牛逼的人也有判断失误的地方”。但是通过上面的分析,我们可以看出这种说法的荒谬性,我们需要清醒的指出,就算没有鲍尔默,微软即便赶上了云计算,他也会错过雾计算;他即便赶上了雾计算,他照样会错过烟计算。

这样的战略,使微软早年站到了时代的风口浪尖,又使如今的微软,变得越来越与时代背道而驰,不是微软不想融合,而是融合的成本越来越高。世异则事异,事异则备变,理解了微软的核心战略,就不难理解微软为什么会去弄什么 xps, silverlight;理解了微软的战略,就能理解为何微软的精力总是在制定新标准,而不是改进老标准了;理解了微软战略,就不难理解为何进入2000年以后,微软总是昏招迭出了。

病在肌肤,还可以医治,病在肺腑,人就危险了。沿袭了那么多年的战略,成就了微软和他的下游开发商,也害了微软,让微软想改变都改变不了。就像一辆陆地上上装甲车,装甲越厚越坚固,然而现在要到水里开战了,所有装甲一夜之间全成了负担,要寻求救赎,除非把自己从头到尾全拆了才行。进入2009年后,看到当年一致支持自己标准的下游开发商们,粉粉判离微软转投敌营时,微软深刻的意识到,老天已经再也不像原来一样眷顾微软了,这真可谓是:成也萧何,败也萧何!

微软的选择

人什么时候会感觉到压力?就是拥有一个东西,但是看着这个东西一天天的减少,越努力抓住他,却又越抓流失的越快,改变意味着放弃,等待意味着死亡。在这样的压力下,微软昏招迭出,这并不能怪微软高管愚昧,也不能说微软运气差,而是自从步入 2000年以后,沿袭了几十年的一家统治世界的战略与时代变得格格不如了。早年的成功让微软无视各种问题,继续靠惯性又活了15年,错过了自我救赎的最佳时机。

核心战略出问题,不是一朝一夕的决策对错,很多人还不愿意承认,认为换了鲍尔默就能解决,认为开源 .Net,就能救 C#,就能救微软,其实这是一个天真的想法。微软战略从头到尾就没变过,开源其实相当于承认先前战略是失败的,可它却又没有提出一套新的思路和新的战略。事实上早在2000年时微软就进入了战略迷茫期,所以东一榔头西一棒子,没有重点,缺乏主题。虽然如此,还是能靠惯性继续生存,但是自我否定之后,新战略是什么呢?战略层的自我否定会极大的伤害企业向心力,让微软在未来变得更加艰难,同时又没有确立能够经得住实践验证的新战略,这又会使整个企业变得比原来更加迷茫。

但微软能改变么?不能。微软没有办法提出一套和原来战略不兼容的新战略,除非完全把自己和多年经营的生态链砸碎。15年前的最佳改变期被其错过后,如今再怎么变都只能在原有战略框架下寻求小改变,时代的巨流,象一股巨大的引力场,吸引着身躯庞大的微软,无可奈何的掉进自己挖的坑里。

无可奈何的结局

直接送货上门发达了,便利店就萧条了。网上购物兴起了,实体零售业也就死亡了。这就叫做 “新经济体” 代替老经济体。判断一个经济体是否衰落,看的从来不是它银行里还有多少钱,而是看它的商业模式是不是还成立。如今的微软,就是一个核心商业模式被颠覆了的企业。这不是开源能够救得了的,更不是盖茨复出能够救得了的。

听到微软开源,让我想起之前 Sun公司 Solaris开源为 Open Solaris,希望用开源来挽救自己的颓势,没多久它就倒闭了。如今一项根本技术,比如操作系统,已经很难被一家公司所垄断。商业模式一旦被颠覆了,开源也不能成为救命稻草。

事物强弱变换,新旧更替,本来就是自然界的基本规律。盖茨是一个聪明人,看到了未来的局面,知道什么叫月满则亏,水盈则溢,在微软最鼎盛的时候功成身退,高风亮节的做起了慈善,将最苦的差事留给了鲍尔默。所以,聪明的盖茨也是不会复出的,所以,其实我挺同情老鲍的。

结尾故事

一开始就没想喷微软,我不是一个极端的人,一开始只是回答问题,建议题主用 Qt,远离微软的技术。但是完蛋了,一堆人上来围攻,那我真得正儿八经的把微软这事情说的清楚点才行了,否则我变成误导题主了。

其实世界是欢迎微软改变的,我们这些从小学电脑就用着盗版微软系统的人,对微软也还是有感情的。但是微软这次能否迎来新生,还得看微软自己,我们是帮不了他的。

给我留言

留言无头像?