Tag Ninayan
之前买了个二手的Kindle4,体验太好了,无论是E-ink屏,还是推送功能,都很舒服,唯一的不足是看扫描版PDF即使切了白边仍然字体过小,如果横屏来看又觉得操作不是很顺手,于是纠结了一阵后,看到有比较便宜的卖全新的DXG的,就趁刚发工资咬牙买了。
昨天早上在taobao拍的,今天下午收到货,然后迫不及待地开箱。没有WIFI就不能免费推送,这是一大遗憾。官方皮套看起来很厚实,装了几本扫描版PDF进去,仍然感觉小了点。官方系统默认不支持中文,书名中带中文的在目录中也不能正确显示,这是点小瑕疵。
忧郁啊,赚的钱远远不够花。这两天遇到瓶颈了,写程序写啥啥不会。想给Ninayan加上链接保存到Readability和发送到Kindle的功能,想想多简单的特性啊,居然遇到很大阻碍。
这两天又重新拾起Ninayan来,随着embed.ly的收费,Ninayan的主打的图片、视频浏览功能被废掉了,只好自己写代码来实现这部分了,但这工作量应该比较大,只能慢慢来了,有点想把这部分代码做成开源项目,叫SANSASORI。
之前也有断断续续地修改,支持Follow5,后来Follow5停运,然后支持StatusNet。这两天主要修改了一下UI,Twitter部分原本就支持使用Twip4的T模式和O模式,只不过没有设置UI,这次把账号设置的UI做了小部分高速,除了可以修改API地址,还为每种oauth服务都增加了用户自定义API Key的功能。这主要是在支持腾讯和新浪微博的过程中,一直遇到因为API Key不能正常使用的问题,如果用户可以自定义,应该能缓解一部分问题。
另外,还在Proxy部分增加了导入用户自定义的SSL证书的UI,这样就可以使用goagent做代理了。不过使用goagent的过程中偶尔发现会有所有网络连接都阻塞不返回,然后不能发起新的网络连接的问题,在网上找了一圈没找到怎么为QNetworkAccessManager的post和get方法设置timeout的方法,纠结。
把文章、图片和视频的浏览功能修复后就不打算再为Ninayan大动干戈了,不增加功能了,顶多就是有bug修一下。之后就开始做KarenMeu了。
之前说过想用Intel C++编译Qt来着,于是从VeryCD上找到Windows、Mac和Linux的Intel C++安装镜象不辞辛苦地下载下来安装。结果让人很沮丧啊。
在Windows 7中,无论编译64位版本还是32位版本,都会编译失败,我怀疑是因为Intel C++用了Visual C++的头文件引起的问题,但是我直接用MSVC2010来编译64位的Qt,虽然也是编译失败,却跟Intel C++报的错误不同,好像C++11标准的问题,在Webkit部分中有类名为nullptr,这个名字在C++11中作为保留字了。也不知道那些用MSVC2010编译成功的是用了什么参数。至于使用MSVC2008的配置,我就没兴趣编译了,因为我不喜欢MSVC2008的SxS。
然后在Mac中编译,32位版本也是编译失败,64位版本编译倒是全部通过了,但貌似make install不完整,那些头文件就没有复制过去,还缺了些什么不知道,反正直接把Qt源代码目录中的include目录复制过去是不能用的。于是也放弃了。
后来么,在Windows上下载了32位和64位的TDM GCC,编译了两个晚上才编译出来,话说那个-nomake "demos examples docs"参数不起作用啊。试了试编译Ninayan 64位,可以运行。
这两天看到Nokia的Qt论坛上有个叫Qt4iOS的人,说他做的Qt for iOS插件就要可以正式发布了,好期待啊。又看到有人说,Necessitas虽然还在Alpha版本,但已经可用性很高了,我看了下,现在居然已经提供4.8.0版本的for Windows/Mac/Linux的SDK了。不过在Mac上安装好后想编译Ninayan才发现,源代码还需要做些修改,比如源代码中通过预定义宏只识别了Windows/Mac/X11/Symbian/Maemon,但是这个Android不知道是什么宏,不知道上哪去查点资料看看。
于是最近还在网上看到的消息,是说Windows Phone的下个版本会支持C++开发,如果这样的话,Qt也会很快就支持WP开发。啊,如果Qt真能用于Android、iOS和Windows Phone的开发,那就太牛逼了。说实话,如果这些port的质量可以的话,只要价格不是太离谱,我应该会买这license去的。
这几天对Ninayan想了很多。
到目前为止,总的说来,尽管bug还很多,UI还不够精致,操作还不够方便,但功能上已经实现了原来预定的计划中的大部分,除了难度最大的按语义自动按用户喜好定义优先级。
最近轻博客突然吸引了好多眼球,大约两年前其实已经有Tumblr这个产品,只是它并没有大火特火起来。而就最近的几个月里,国内突然冒出好几个同类产品,点点,推他,据说新浪有个Qing。虽然像Twitter、新浪微博这种都有自己的方式展示多媒体信息,但用过轻博客后,明显感觉体验更进一层。于是我就想,其实从客户端层面出发,可以尽量抹平微博客和轻博客的差异,Ninayan就可以往这个方向发展,如果真这么做,无论UI还是底层,都需要做大量修改。
这些天我用新浪微博比较多,同时又不想落下Twitter,同时比较认真地维护两个账号,让我突然意识到,像我这样的人用微博,主要出于两个目的,一是分享自己的状态,二是获取自己关心的信息。而获取信息又可大体分为主动和被动两种,主动是指自己去主动阅读timeline,被动指被别人mention了。于是想到对于同时维护多于1个账号的情况下,提供一种合并显示所有账号的同类信息的功能会很有用,Mixero就有这种将多个账号的timeline显示到一块儿,mentions显示到一块儿等等这种选项,而Ninayan要做的则是可以跨服务合并显示,即比如把Twitter和新浪微博的timeline显示到一块儿。这样做会引发另一个问题是,过滤掉重复信息。这一方向得靠用户自己,仔细甄选该关注的人,比如有的人喜欢用同步工具,结果ta在多个服务中发布的消息几乎是一样的,那么只要在某个服务中关注ta一次就够了;另一方面可以在软件层面识别出相同信息进行过滤。另外要说的是,分享活动,最好是能随时随地方便地进行。这就是说,Ninayan目前光有Windows/Mac/Linux桌面版是不够的,还应该有iOS版和Android版,除了手机版,还要有平板版。还有,最好能自动截取到用户关心的活动,比如能自动获取当前系统中正在播放的歌曲的信息,浏览器正在浏览的网页的标题等等。
暂时就想到这样,好吧,可以做很久很久了。
终于大体上对iOS有一个模糊的轮廓了,做一个没有特别的技术点或者奇异的UI的app的话,基本上靠翻书和查手册应该能搞定了,就像几个月前开始用QML写Ninayan一样。
昨天被ObjC和Cocoa Touch给联合调戏了,我居然以为任何对象都可以随便release。实际上release了不该release的对象后,就会出现各种古怪的问题。
另外有件让我觉得比较蛋疼的事,苹果居然为了用ObjC实现一个singleton而提供了一段官方的样板代码,囧死了。
实在有点不乐意做Deardawn,心理障碍克服不了啊。
Ninayan今天被小言一说,才发现真的是添加不了账号了,原来是之前一次为了加快启动速度的修改,把其他功能破坏掉了,不但添加不上账号,还一开始不能发布消息,只有在显示过home timeline后才可以。
提取了几个model类,这样的实现比较优雅。
几个singleton在程序退出时都正确销毁了。
把AutoProxy的gfwlist信息配置保存到sqlite数据库里了,可以记录每条规则的enable与否,hit次数。在每次程序退出时刷新这些信息到sqlite数据库里。
给几个本地数据库建了几个索引,这样可以让查询速度加快一点点吧。
由于占用内存比较厉害,在Windows下就用::EmptyWorkingSet每分钟清空一次工作集,其他平台不知道有什么类似的方案。但实际上在Windows下如果窗口最小化时,内存会被一下子回收好多,不知道到底是怎么回事的。
本地数据库读写冲突的问题还没想到比较低成本的解决方案,叹气。
停下来想想,现在已经实现的功能也只是玩玩而已,最有用的应该还是Google Reader支持吧,可惜没找到确认无误的API文档。
blog被墙了就真不太想更新了。
Ninayan这段时间除了不时地发现些bug,然后修正外,主要是增加了对163、Sina、Sohu、QQ微博的支持。从开发者角度讲,163的API是最接近Twitter了,QQ的API设计最山寨,完全自己搞了一套,Sina和Sohu从技术角度讲跟QQ接近,接口设计仍然是模仿Twitter。
然后在google code上放了Linux版的可执行文件上去,今天才知道原来各发行版上普通的应用程序是可以做到二进制兼容的,也怪我以前看CodeLite、Code::Blocks它们都为每个发行版提供一个独立的安装包,就先入为主地以为每个发行版都要各自单独编译才行。今天突然想到Qt Creator就是同一个可执行文件在所有Linux发行版里可以运行,只是区分了32位和64位而已。我还傻乎乎地在12个系统里都编译了一把Qt,再分别编译出Ninayan,再分别打包,再分别上传,天呐!
首先一件很郁闷的事,貌似域名被墙了,直接用IP是可以打开本blog的,但是我暂时又不想去折腾这些了,先这么放着吧,问候下方校长18代祖宗及全体女性家属。
Ninayan最近动作倒是不大了,主要是先打了Mac,Win32和Linux的安装包给几个人试用了一下,结果反响很差,有点失落,难道真的定位有问题?
不过说起来,Ninayan现在也只是个雏形,真正的主要的理念需要的特性并没有实现,现在也只是把图片,视频和文章链接单独提取出来可以独立浏览而已,并没有做进一步的工作,比如要能打tag,可以检索,自动语义过滤,优先级排序等等。其次是RSS聚合也没做,Google Reader没实现,UI缺少专业的美工设计等等,总之可以做的工作还有很多很多。
另外,今天勉强让Ninayan在我的Nokia 5230上运行起来了,解决了不少问题,但最终还是由于报内存不足而自动退出。为了让Ninayan可以在5230上运行,遇到了不少问题。首先是开发环境的建立,我用的是Qt SDK 1.1 beta,这个SDK用的是Qt 4.7.2,但有bug,for S60v5的配置文件使用了for Symbian^3的配置,所以编译工程的时候会出错,要自己在工程的.pro里把opengl的配置去掉。其次是部署时,要安装Qt,还要单独安装sqlite,据说以前版本是合在一个安装包里的。最后是这两天一直在纠结的问题,运行后在TextInput获取输入焦点后,虚拟键盘没有显示出来,在Nokia的论坛和Stackoverflow上问,都没人回复,今天偶然想起qDou,试了下它在5230上至少是可以输入文字的,虽然之后会崩溃,于是发邮件问了一下作者,作者给了个网址,原来是我在TextInput控件一起放了个兄弟控件MouseArea,于是TextInput没能收到点击事件,于是虚拟键盘不会自动显示,只要自己强制调用它的openSoftwareInputPanel方法就可以了。
至于最后的自动退出,从现象结合网上的人们的讨论来看,似乎是因为同时请求的网络连接太多,以及内存占用过多引起的。叹气,桌面程序写惯了,散漫惯了,都不怎么注意内存的使用了,反而经常采取以空间换时间的策略,看来如果真要让Ninayan能在手机上正常跑起来的话,还得好好重新设计一下,把各种请求都放进队列里,不要一下并发几十个连接,其他的内存使用策略也得仔细看看,有点想看看侯捷翻译的那本讲内存受限系统的程序开发的书了。
Ninayan的主要功能基本上都做出来了,剩下的主要是增加各种服务的支持,比如各种微博,各种SNS,以及Google Reader。其次便是界面和操作上的细节方面的调整,现在还是很粗糙的。
离上次W.I.P.已经有3周多了,这3周主要实现了文章浏览特性。文章浏览有3种模式,一种是仿feedly的可扩展的列表,一种是信reeder的分栏,还有一种是仿paper.li的报纸模式。但是,目前的效果还远远没达到预期。放几张图吧:
还增加了个视频观看视图,这是计划外的,但觉得有必要,也很粗糙:
直到这里才发现,在Mac OS X 10.6.6上一直以64位Cocoa编译的Qt,果然视频播放不了了,不记得在哪里看到过说明,QtWebKit在Mac上如果是64位的话是载入不了Flash播放插件的,因为Flash播放器稳定发布只有32位版本,于是在Mac上也自己编译了一把Qt,改成32位Cocoa框架的就可以了播放视频了,太纠结了,也难怪乔帮主要封杀Flash了。
今天觉得Ninayan大部分功能已经实现了,也差不多快可以发布beta版了,于是要打包,先解决Windows和Mac上的打包问题。 Windows上一直以来我都习惯用Inno Setup了,所以在如何制作安装包的问题上并不纠结,InnoIDE和ISTool都是很方便的工具,主要的问题在于解决Qt的插件的部署。Ninayan在Windows上也是用GCC(MinGW)编译的,相比VS2008,少了个SxS的问题,只要带两个dll一起发布就行了。Qt本身有一种简单但比较有用的插件机制,它的字符编码支持CJK,图形文件格式支持,数据库驱动等等都是由插件实现的。也就是说$(QTDIR)/plugins下的东西都要跟着发布,而且程序代码中需要自己在main()中,app对象创建后及时调用QCoreApplication::addLibraryPath()添加plugins的路径。另外由于用到了QtWebKit和QML,QDeclarativeEngine对象也需要指定一下qmlwebkitplugin插件的目录,把$(QTDIR)/imports/QtWebKit目录打包进去,然后在代码中调用QDeclarativeEngine::addImportPath()添加路径,这样整个目录就是发布的所有内容了。 在Mac OSX上比较流行用dmg,但这之前还要解决Qt的framework链接的问题。Qt在Mac OSX下官方发布的二进制包是framework形式的,这跟Windows下有点不同,呃,其实跟SxS有点类似。要用install_name_tool -change命令行修改自己的程序可执行文件链接的framework的位置,这个工作可以由Qt自带的一个叫macdeployqt的小工具完成,只要在命令行执行macdeployqt Ninayan.app就可以了。不过除此之外,还是由于qmlwebkitplugin的缘故,需要自己复制这个插件到程序的bundle中,我就放在跟最终的可执行文件相同的目录中,这个插件macdeployqt并不处理,除了要自己复制,还要自己用install_name_tool来修改链接的framework。这样操作后,是一个可以正常运行的,完整的应用程序bundle,整个bundle就有113MB,谁让Qt那么大呢!然后是把这个bundle打包成dmg。Mac OSX自带免费的工具,GUI和CUI的都有,GUI的叫Disk Utility,不过看了下感觉界面挺复杂的,还是用命令行的hdiutil爽,而且我前面是用命令行修改的符号链接,这里当然最好也是用命令行打包,这样一个shell脚本就能搞定编译后生成dmg的所有事情了。用hdiutil的话,这个命令行就可以打出一个dmg来: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDZO -ov Ninayan.dmg 不过这个有点土,就是把Ninayan.app放成了dmg而已,其他什么都没有。我的要求其实也很简单,有自定义的背景图片,有Applications目录的链接,这样用户打开这个dmg就可以完成把Ninayan拖拽到Applications目录中的操作。在网上找了不少文章和视频,多是用其他的GUI工具,在stackoverflow上有个家伙用AppleScript写了段脚本,确实通用性和灵活性都比较好了。最后我选了条简易简陋没通用性的路子,但够用。首先需要明白的是,dmg被Finder打开后,就是当成一个普通的文件夹处理的,所以它的背景什么的设置,都是放在.DS_Store文件中的(Mac中以dot开头的文件都会自动隐藏),所以很dirty的做法是,先用这个命令行创建一个可读可写的dmg并挂载: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDRW -size...
已经不记得有几个大年三十的晚上是在电脑前写代码度过了,今年破天荒的因为客厅里电视在放春晚,打偶然走过去看几眼。
今天把超链接处理模块重构了,之前那个实现在Mac下崩溃得比较频繁,但在Windows和Linux下却不是很多。对于这个现象我有点疑惑,虽然说代码确实是写得有问题,但为什么只有在Mac才比较明显呢。好在Mac下崩溃了打印出来的栈回调信息比较详细,几乎能跟踪到最终引起崩溃的代码行。
原来的实现把所有中间数据结构以指针的形式保存在一个list里,然后在自认为结束的时候销毁对象。这样的做法本没有什么问题,关键是我在操作这个list时并没有考虑重入的情况。于是重构主要做了两个重大修改,一是在list中直接保存对象,而不是指针,这样更不容易写错;二是对list操作大部分情况下都加mutex锁住。顺便也修正了些其他的小问题,比如原来即使是基于embed.ly的服务识别url是图片还是视频也有问题,其实embed.ly是返回了这个类型的。
另外,今天还把主界面针对360*640分辨率修改了一下,因为Nokia的S60v5和Symbian^3现在几个机型都是用这个分辨率的。至此,图片浏览特性的实现暂时告一段落,接下来该实现文章阅读了。昨天大致研究了一下Readability,发现它在Firefox表现那么风骚,结果在QtWebkit下总是返回不能分析的错误。不知道是DOM树的实现还是JavaScript引擎的问题。难道真要我移植一个C++版本,这实在太费时费力,还不好维护了。
最后,上个最新界面截图。
终于勉强加上了一个功能比较凑合的图片浏览功能,还有很多地方需要改善。本来我的想法是UI上直接拿QML Demo PhotoViewer的代码来用的,可是昨天发现PhotoViewer中的代码会导致在Windows下程序不能切换输入法,于是只好自己写了。自己写就极大地简化了功能,才简化了代码,于是最后所有东西都放在一个QML文件中写完了,最终的效果,也就是几个视图场景切换时那个动画效果没有了。残念!
另外有个问题是图片下载的问题,现在的Twitter上比较流行的图床大多是被墙的,如果让QML的引擎自己通过代理下载图片,感觉不是一般的慢!所以我就觉得把这些图片事先下载到本地缓存起来似乎挺有必要的。
还有个比较重要的问题是全屏模式下浏览图片,默认是自动拉伸到整个显示区了,这样似乎比较影响显示性能,当然也是机器配置不是那么好的才会有这种卡的情况,在我的T43上会卡,拿到Mac mini上就流畅了。应该稍微改一下,看一下是不是在加载前就获取图片本身的尺寸,如果比显示区域大,才缩放,不大的话,就以图片本身的大小显示了,这样显示也更清晰点。
还有个浏览某张图片的大图就不截了,没啥好看的。
有些问题,总是那么奇怪。因为XP里的虚拟机在跑Debian编译Qt,于是在Mac下把QML的Demo PhotoView抠过来用,本来就很吃力,还顺带发现了一个因为先后顺序问题引起的崩溃bug,终于可以在Ninayan里看到PhotoView的样子了。可是到了晚上突然发现,在Windows下不能切换输入法了,一切换Ninayan就挂死!经过一部分一部分地屏蔽代码发现,引起这个问题的似乎是VirtualDataModel中Package的一些代码。好吧,决定索性不用抠别人的代码,用自己的方法写一遍相同的UI吧。
上一段提到,我又蛋疼地在Debian里编译Qt了,嗯,又花了一下午。之后就是编译Ninayan,呃,我现在最大的乐趣就在于在不同的系统里编译Ninayan并用它来上Twitter了,囧rz。想来也不会有多大问题,毕竟之前在Arch和Mint里都比较顺利的,唯一大的区别是在Arch和Mint里桌面都是用Gnome,而这次Debian里用的是KDE,很花哨的感觉。言归正传,Ninayan运行得很顺利,除了字体不太好看。在Twitter上报怨了一下后,@truthurt建议自带一个开源的字体,真是个不错的主意,在Mint里的那种就很好,我后来去网上找了文泉驿的微米黑,在Debian和Arch里效果都很好。其实昨天就想过字体的问题,不过当时想到的是直接将字体装入到系统中,然后在程序中直接通过字体family名使用。今天偶然想到,其实可以程序直接载入指定路径的字体文件来使用的!不过Windows下还是用微软雅黑吧,微米黑在XP下同一个字的不同笔画都有粗细差异,真糟糕。
今天照计划,实现了查看对话的功能,不过不完善,因为网络传输的原因,是一条消息一条消息从服务器获取后显示,如果显示到一半切断,又要显示另一组对话,就会把前一组对话后面没显示的那些消息作为后一组对话的消息。所以要考虑一下怎么加一个中断的机制,不过这个留到以后版本中完善吧,毕竟Ninayan一开始定位就不是一个完善的客户端。
然后又蛋疼地去装ArchLinux了。这个发行版安装比Ubuntu麻烦多了,它的iso镜像只装一个最基本的字符界面,然后带一个pacman包管理工具,GNOME之类的桌面需要自己再另外安装,所以最好有比较畅通的网络。
装完后,中文字体的显示惨不忍睹,google随便搜了一下,也挺折腾的,我懒得弄了。我就是想在上面试试编译Ninayan。没想到可以用pacman安装已经编译好的Qt 4.7.1,再装个Qt Creator,就可以编译Ninayan了。除了显示的字体不好外,其他的还算凑合吧。
明天开始做图片浏览和文章阅读功能吧。
昨天和前天晚上蛋疼地在Linux上编译Ninayan了。我用的是Mint9,也就是一个Ubuntu的修改版。在Linux上编译Qt程序有点麻烦的是需要自己编译一遍Qt,前天晚上就编译了一遍最新的qt-everywhere-opensource-src-4.7.1.tar.gz,过程比较顺利,再装上Qt Creator就可以编译出Ninayan了,简单试用了一下,很正常。而且令我比较惊讶的是,我学Hotot用了Droid Sans字体,最终的显示效果在我个人看来比Windows XP SP3和Mac OS 10.6.6上都要好,但XP SP3上加上Gdipp或MacType后,效果会有很大的提升。
昨天突然发现,Ninayan在Mint下不能访问https://api.twitter.com(不是被墙的缘故),测试了几次才确认是不能访问https的地址,于是想到前不久看过一篇博文说Qt 4.7是有这么个bug不能访问https的,因为原来Qt 4.6带了SSL证书,而Qt 4.7没带,于是照那篇文章的作者的说法,从Qt 4.6.2里找到qt-ca-bundle.crt文件,然后每次QNetworkRequest在被post或get前都设置一下Ssl证书。结果我的情况是连编译都不通过,于是可以确认是Qt在编译时没有编译进OpenSSL了。然后找到了这篇《Compile Qt 4.7 on Ubuntu 10.10》,先要安装一堆的库的开发包,再来编译Qt,最后再编译Ninayan,果然就正常了!于是我就不明白那篇博文讲述的到底是个神马问题了!
今天就比较烦躁地在做网址缩短功能了。本来打算内置goo.gl,bit.ly和is.gd三个短网址服务,结果很郁闷的是bit.ly总是返回INVALID_URI,但同样的URL我拿到Firefox下测试就能返回正确的数据,这不是歧视嘛,难道是在http header里还要设置神马东西?倒是goo.gl和is.gd都正常了!
话说前天偶然发现了MacType和Gdipp,觉得这种功能对Ninayan之类偏阅读的应用非常有帮助,于是我在极限论坛上给MacType的作者私下发了个email询问是否可以提供专门的API以便集成此功能。不过到现在也没收到回应,估计是不愿意了。
今天看了一下MacType的安装目录,发现有个MacLoader.exe,而Gdipp的安装目录下也有个loader文件,这时才明白过来,可以通过把可执行文件的完整路径作为命令行参数传递给这loader,那么该可执行文件会被启动运行,并被注入实现字体渲染增强效果。
经过简单的测试,Ninayan在我的XP SP3上使用微软雅黑字体,加上增强字体渲染效果,感觉确实更舒服了!而Gdipp是以GPLv3,最新的版本好像是用LGPL了,一起打包发布应该是木有问题的。我只要另外再写一个小小的启动程序,在安装包中把启动程序作为快捷方式添加到开始菜单和桌面等位置,可以自己调整是否使用增强字体渲染效果,使用什么样的渲染配置等等。
这样一来,似乎Windows上的效果都超过Mac上的了,一直没找到感觉特别好的Mac上的用于大段文字阅读的字体,微软雅黑只适合在Windows上用,而且至少要开了ClearType Tuner才行,有MacType或Gdipp最好。也许是因为我在Mac下用的是CRT的显示器的缘故,不止一个人对我说过那个视频信号转换后损失挺大的,也许用LCD的就要好些了!
今天心情不错,呼呼!
前面说到内存泄漏的问题。后来通过逐段屏蔽代码,终于找到了最大一处泄漏源。这个办法比较笨,但这次真的有用,主要还是因为程序结构简单,流程也不复杂才能用吧。
程序大体上分为三部分,UI层,数据层,网络通信层。用户在UI层上操作,1、UI层向数据层请求数据,2、数据层根据不同情况直接查询本地数据库或通过网络通信层获取数据,3、网络通信层自己有一个定时轮循的任务,每分钟从远程服务器获取数据,4、有了数据就发送给数据层,5、数据层将数据经过简单处理发送给UI层,6、然后显示,就是这么简单。
我开始主要怀疑UI显示调用的Qt/QML也许MM有问题,于是把最终UI显示的代码屏蔽掉。发现仍然泄漏的情况基本没有变化,说明跟UI显示的关系不大。后来发现Mem Usage的增长是有周期,大概是1分钟1次,那么可以确定是在4和5两步有问题。这时把第5步中代码全部屏蔽掉,果然Mem Usage就不增长了。然后逐步缩小范围,一点点放出代码,最后发现竟然是QSqlQuery查询本地数据库时,select出来的东西需要程序员自己clear掉!内牛满面啊,果然是Qt用得有问题!
今天偶然发现一个叫MacType的东东,可以在Windows下以进程注入的方式给指定进程增强字体渲染效果。跟微软官方的ClearType Tuner是一类东西,不过MacType的选项更丰富。于是我想到,我这个以阅读为主的工具,要是集成这么个美仑美奂的功能,该是多酷啊。在极限论坛翻了一遍帖子,貌似MacType是闭源的,另外有个新生的Gdipp项目,倒是在googlecode上开源了,不过听说它的配置复杂,而且目前不够稳定,尤其是32位系统上。好吧,反正这种功能对我有致命吸引力,一定要集成!
内存泄漏的问题,调得我心力交瘁,都有点神经衰弱了,甚至有点绝望,唉。以前还真没有过这种强烈的负面情绪出现过。
每次UI刷新,从任务管理器里看Mem Usage都会增加2-3MB,这得有多严重的泄漏啊!可是我自己的代码中new出来的对象都经过跟踪是销毁掉了的。于是又把矛头指向Qt内部,或者是QML中了。
本来怀疑是QML中的实现可能有问题,于是把Qt从4.7.0升级到4.7.1,貌似泄漏得更严重了。所以现在都已经不敢怀疑是Qt有问题了,开始怀疑是没有遵循Qt的用法。有些Qt返回的东西,需要程序员来负责销毁,比如QNetworkAccessManager在调用get或post后返回的QNetworkReply对象,这是多么操蛋的设计啊,指不定就是每次在哪里它自己创建出一堆对象出来要我来销毁我却不知道呢!
从CodeProject上下载了个Visual Leaks Detector,从说明上看,说是在msvc的jit debugger里会自动打印信息到debugging output window里的,可我实际上试了之后,发现屁都没输出一句,难道它是for MFC-based project only的?有可能的,唉!
简直走投无路了。
本来排除在计划外的事情,今天又去搞了,就是支持Twip4。前一天也折腾过一下,没弄好,这回问了一下Twip4的作者@yegle,他开始说是计算数字签名时用https://api.twitter.com/作为base string就行了。我试了下不行,后来他又说试试T模式吧,有几个客户端是经过实践T模式没问题的。于是一下子就明白过来了。 Twip4有T模式和O模式两种工作模式。T模式是完全的透明转发,Twip基本上不做任何处理,所以要请求oauth token和oauth token secret时原本是向https://api.twitter.com/oauth/access_token请求的,同时也是拿https://api.twitter.com/oauth/access_token作为base string计算数字签名的,在使用T模式的代理时,只要向http://www.myproxy.com/oauth/access_token请求就行了,仍然用https://api.twitter.com/oauth/access_token作为base string计算数字签名,这样就能无障碍获取oauth token和oauth token secret了。至于O模式,我看了下TweetDeck和Mixero的表现,发现它们也并不向O模式Twip请求oauth token和oauth token secret,或者请求了也没结果。所以我就推测其实O模式是没这功能的,O模式自己有consumer key和consumer secret,所以自己有一套oauth token和oauth token secret,但不是给客户端用的,即使客户端用自己有效的oauth token和oauth token secret发送给Twip请求,Twip也会把http header和url parameters里的东西处理一遍,用自己的那套oauth token和oauth token secret计算出来的东西替换掉。所以我想如果用O模式也要让用户可以无障碍认证的话,需要软件自己提供一个透明代理,软件先拿用户名和密码从那透明代理处获取oauth token和oauth token secret,然后在其他发布消息,收取消息时用O模式代理,就可以解决这个问题了。...
好吧,其实没做什么,本来的计划是先做图片浏览和文章阅读的,可是饭否上的内容实在太单薄了点,呃,这纯粹是借口,于是今天实现了对Twitter的支持。
昨天晚上弄到1点半才基本搞好怎么用xAuth认证获取oauth token和oauth token secret,今天就把twitter的timeline浏览,direct message浏览以及消息发布实现了。这内容比饭否丰富了许多,比如有了3列跟retweet有关的内容。twitter居然没有像饭否那样可以一次请求把foing和foer列表取下来,而只能先获取那些id,再由id去获取其他信息!于是这个功能就还没实现。还有比较影响使用的没实现的功能包括不能看conversation,不支持list,不能用快捷键操作。
不过有点值得欣慰的是,又修正了几处内存泄漏的问题。
今天就不上图了,因为基本上界面上没啥变化。
脑袋混沌了一天,终于基本上搞定超链接处理的功能了。
最开始是由于我使用的处理流程的关系,选择一个合适的数据结构让我头疼了好久,最后决定使用一个list,每个元素是一个结构体,每个结构体由两部分组织,一部分是URL列表,该列表会按短网址还原后的处理顺序存储URL,另一部分则是对该URL的描述,描述的字段包括当前是否已经完成全部的还原操作,最后一个URL能不能被embed.ly拆成两个新的URL列表,代表视频的html和html5等信息。
中间调试过程也是经历了重重磨难啊!其实也是自己代码写得有问题。一开始我是用一个map来存储url list和附着属性的,指针乱飘,调试得没有信心了,才改成上面描述的那个方案。还是有很多问题,经过层层排查,终于把所有的问题都找出来并解决掉了。甚至以为Qt的signal不能随便emit,会有对象生命周期相关的问题,最后也确认其实是在前面的代码写得有问题,哇哈哈!
明天就看一下怎么把数据库中的已有记录读取出来当历史记录来处理超链接。然后就可以做图片浏览的功能了!图片浏览功能完成后就做Readability的功能,之后再做twitter的支持,这就可以发布第一个版本了!
根据@zhangh109的建议,修改了一下界面,浏览文章有三种模式,在启动界面现在就只有一个入口Article View,在Article View中再添加切换浏览模式的入口。另外了加个图片浏览的视图,在启动界面中把原来About的入口替换掉了,About则移到原来的Quit按钮处。
URL处理部分今天还是没有搞定,不过思路清晰了很多,估计明天就可以完成总体的框架,到时候图片浏览部分应该就可以很快实现,而文章浏览部分需要把Readability的JavaScript代码移植过来,本来如果可以直接用它的那些JavaScript代码是最好的方案,可是之前我曾尝试过,不知道为什么内嵌的Webkit在装载完页面后,直接运行那个代码是没有作用的。所以干脆也不研究它了,直接移植成C++的,用Qt的接口操作Webkit的DOM树来解决吧。想来这移植工作需要花一些时间吧。
贴两张修改后的截图吧。
今天在处理超链接的问题,这是最重要的一环。
Ninayan提供给用户的信息分两大类:图片/视频和文章,微博消息只算是附属品。所以从微博消息中得到一个URL后,最终要能正确识别出它是一个图片/视频,还是一篇文章(当然,文章中也可以有图片和视频,但重点是它有文字),对于其他不可识别的类型,比如zip,则忽略。
我设计了如下的处理流程:
1、将URL与embed.ly可处理的类型用正则表达式匹配一下,如果可以匹配上,则用embed.ly处理,不能匹配上,则假设它是个短网址,将其还原成长网址。
2、embed.ly处理后,会返回缩略图和原图(如果是视频,则是一段HTML,可能还会有一段HTML5代码)的URL,假设这URL也是个短网址,也将其还原成长网址。
3、还原成长网址后,与原来的短网址比较,如果两者不相等,则假设该长网址仍然是个短网址,继续还原,如此循环迭代,直到还原失败或两者相等,最后还原的最终长网址与embed.ly可处理的类型用正则表达式匹配一下,如果可以匹配上,则用embed.ly处理。
4、如果第3步最终的长网址不能与embed.ly匹配上,则认为该网址是真正的最终应该由Ninayan处理的网址,可分为前面说的两类,图片/视频和文章。
至于怎么辨别出属于哪一类,我决定采用一个很粗糙的办法,如果前面经过embed.ly处理过的,那么肯定是图片/视频,或者URL最后是以诸如.jpg/.png/.gif等known的图片/视频文件扩展名结尾,那么也是图片/视频,其他的则都划入文章类型。而文章类型其实是个很粗糙的结果,网页是要经过像Readability那样的处理才是最终显示给用户的,而在Readability处理的过程中,可以过滤掉诸如.zip等不支持的文件类型的。
这个方案也只是考虑到了URL在网络交互上的处理过程。还有这处理结果怎么通知本地数据存储模块和UI显示模块,也是个问题。而这个问题涉及到何时通知,通知时采用什么数据结构,以及本地存储时采用什么数据结构。
添加了个图片本地缓存的功能,结果发现不是很好用。在Windows下实际使用时发现有时候装载本地文件仍然很慢,甚至不如直接从网络上加载的快。在Mac下发现压根就装载不上。初步估计是因为多处同时读写文件时有冲突,需要再仔细看看。
把删除消息,去fav后的响应也添加上了。
另外还有些细节方便的调整,比如所有显示图片的地方都添加了等待动画。
最后发现个奇怪的问题,在Mac下读取Friends列表有问题,json解析失败,这太诡异了。
今天听@shellexy说,用HTML5的话,配合JS/CSS这些东东,可以实现跨iOS/Android/WebOS/Symbian/MeeGo,呃,这也太强大了吧,而且据说Hotot移植到这些平台已经是在计划中了。得好好考察一番这种开发方案了。
昨天突然发现有内存泄漏,确实找到几次没有释放的,后来从任务管理器里看,貌似还有泄漏,但实在找不出有什么地方有问题了,最后今天把所有自己new和delete都放在一个类中统一调度跟踪,发现确实是都正确释放了的,只好先不管了。
今天搞定了显示friends和followers列表的功能,增加了显示所有自己发布的消息的功能。明天就搞一下显示之前的消息的功能。之后再修改一下消息显示的格式,比如图片预览,超链接处理等,然后就算是完成一个milestone了吧。
不多说,也是上两张图,还被@shellexy嘲笑了说~
经过一天的折腾,Ninayan已经能完成跟消息相关的绝大多数操作了,私信也搞定了。作为一个纯粹的微博客户端来说,也就剩下图片上传和用户Profile查看没做了。更多的诸如图片预览等功能属于比较有用的增值功能,不在这个范畴内。
汇报一下进度,Fanfou的API果然是最简单的,现在除了可以浏览时间线,回复线和收藏外,已经可以做些基本的操作了,比如发消息,当然包括回复,收藏和取消收藏,删除消息。而且也把消息都保存到本地了,每次切换页面时,显示消息的速度就相比以前会快一点,以前是每次都要从服务器上取下来才能显示。
接下来要解决的是,发布消息后刷新界面,以及消息中的超链接处理等细节问题。
今天折腾下来后,已经可以浏览饭否的最新的timeline,mentions和favorites了,当然,也仅仅只是能浏览而已,所有其他操作都还没做,不过至少证明这个架构是能正常工作的。上张截图吧:
其实是个小功能,真正实现起来还是有点花时间的,那就是移植AutoProxy的功能。在Ninayan中的过程大致如下:
1、从本地读取gfwlist.txt(假如存在的话),然后应用到代理管理器中;
2、从googlecode的svn上下载到最新的gfwlist.txt,然后应用到代理管理器中,如果第一步已经成功执行过了,那么这步的应用到代理管理器的操作会被略过;
3、将下载到的gfwlist.txt替换本地那个老的gfwlist.txt。
应用到代理管理器也不难,首先将gfwlist.txt内容全部读出,然后Base64解码,按行分隔,除掉空行和注释行,剩下有效的规则大约是2700多条。规则分为5类,分别是关键字匹配,主机域名包含匹配,正则表达式匹配,开始字符串匹配以及一种优先级最高的强行不代理规则的匹配。
现在的问题是,代理似乎是能正常工作了,但感觉有点性能问题。于是我就想是不是应该想点其他办法加速这个匹配过程,比较容易想到的是做个简单的缓存,比如已经被匹配过的,需要代理的URL就保存到缓存中,以后有新的代理验证请求来的时候,先在这个缓存中找是不是已经有过,如果有了,就直接返回。这是基于这样一个假设:用户浏览的网站比较集中。而且这个缓存不能大,粗略地想想,可以保持在几十或几百个URL的容量,然后每个URL要维护一个计数,如果缓存一满,就把计数最少的删掉。不过这要注意一个问题,如果时间一长,缓存中的每个记录的计数都很大,然后新的URL就再也进不了缓存了。这种情况很容易出现,比如用户突然从某天开始关注起一个以前都不关注的网站了。其实这个问题也有个笨的简单方案,就是为每个被规则匹配成功的URL都维护一个计数,然后定期选出计数最大的一批URL进缓存。不过这些只是我现在的构想,不知道是否可用,先放着吧,这个问题不是很急。
最后,传张代理配置界面的截图吧,这回是真实数据了。
兵马未动,粮草先行。第一次用Qt,第一次用QML,用QML Viewer做原型,可以强迫自己界面与逻辑分享,大赞啊!于是先把几个主要部分的界面用QML画出来,当然,所有显示的数据都是假的。现在还没想好显示和操作微博的界面应该弄成什么样,本来想模仿FaWave的,可是前些天Reeder把MobileRSS的界面抄袭抖出来后,弄得我不好意思抄别人的了,继续发呆神游天外。先放截图上来,其实用QML的主要原因除了比较容易做出漂亮的界面外,还因为操作上有各种动画效果,这里静态图片上就看不出来了。
另外还有个Paper视图,以paper.li的那种排版显示内容,其实就是一个网页浏览器,现在也没有可看的内容。
腾讯也开放微博API了,这对于一个一贯坚持封闭的公司来说,真是个很艰难的决定。但是,眼下的互联网环境中,开放已经成了大趋势,想想Facebook和Twitter这两种SNS的代表形式,由于API的开放,第三方的应用和客户端真是百花齐放,争奇斗艳,不开放就是死。腾讯在推出微博服务的时候,我猜他们一点都不担心自己的用户数,因为他们自以为有庞大的QQ用户基数支持,只要让QQ客户端支持微博,就能顺利将用户转移过去。事实是国内使用微博的用户,绝大多数不是使用网页端,就是使用手机客户端,同时可以想像得到,目前的QQ死忠用户鉴于他们的年龄,知识构成,社交习惯等因素,很难迅速接受并支持微博这种表达方式,对他们来说,QQ签名就足以支持他们对微博这种媒体形式的需求了,那样更方便,更直观。
开放API,并不是说将微博功能从网页端到其他桌面端或手机端实现一遍就完事了。Twitter在这方面无论是官方还是第三方都有不少的尝试,当然这也跟服务商对微博的定位有关系。比如Twitter之前说过他们做的不是社交服务,而是新闻服务,提供的是内容,所以Twitter官网的上次大改版就是往这个方向上发展的,它更注重内容的展现,希望用户可以方便快捷地获取到各种信息。而国内的诸多微博服务,无一不是停留在最原始的框架下,对于信息的回溯检索,或是扩散都没有任何明显的形式的支持。就像之前ifanr对和菜头的访谈中提到的那样,国内的微博在意识形态上仍然停留在精英制造内容,草根膜拜瞻仰的原始阶段。
这些天推友@lucifierya一直在推一些他对个人知识管理的想法和实践,他主要偏重从网络上获取的信息,包括RSS、Blog、Tweet等。其实这三部分独立的,都有各种实现得很好的方案,两种或三种结合的也有一些方案,但显然就很不被重视了。再回头说腾讯,腾讯有QQ阅读器,有QQ空间,也有微博,三者也有简单的关联,比如QQ阅读器中可以看到好友最新文章,但也仅此而已了。我对@lucifierya的一些想法深以为然,但也许因为他个人缺少对软件开发方面的知识和技能,他提供的解决方案就有点畸形。我在上Twitter的这一年来,一直在考虑自己实现一个Twitter客户端,一开始只是一个单纯的客户端,后来想法就逐渐有所延伸和扩展。单纯的客户端并不是我想要的,我的本意是需要一个获取信息,管理信息的工具。考察和试用了不少其他的服务,想法已经比较完整,但尚未明确和具体,大致如下:
1、连接各微博服务,当然首要是Twitter,提取微博中的网址超链接,作为一个信息源。
2、连接各书签分享服务,比如Delicious,ReadItLater,Instapaper等,作为第二个信息源。
3、订阅RSS以及Google Reader,作为第三个信息源。
4、方便地将超链接分享到微博和书签服务中去。
5、将网页主要内容提取显示。Readability、iReader等扩展的作用很明显,可以极大地提高用户体验,但将这功能放在浏览器中需要用户手工激活,有点繁琐,而在专业的内容阅读器中默认采用这种形式就方便了。
6、将所有内容条目以列表形式组织显示,如Feedly或Reeder那样,可以看到每个条目的开头的一部分信息以及内含图片的缩略图,用户就可以直接判断是否是自己感兴趣的内容。
7、将所有内容条目以报纸排版显示,如QQ阅读器或http://paper.li那样,这样除了有上一条的好处外,更多的是一种贴近传统习惯的用户体验,至少我个人是相当喜欢这种形式,只不过QQ阅读器一页显示的内容太少,以及不能自行添加RSS订阅,而http://paper.li时有乱码,更新周期太长,并且导致有时候一页内空白块太多,不够美观。
8、用户可以对内容添加评论,评论内容和相关链接可以保存到Google Docs上去,这样就可以移动应用了。
以上这些就是我总结出来的大的需求,其他小需求暂且不提。我会自己用Qt慢慢实现,以目前的能力来看,至少可以实现跨Windows/Mac/Linux/Symbian/MeeGo了,也许以后Qt移植到Android和iOS上后,也会支持Android和iOS吧,这是后话了。
在前些天的Nokia World2010中,Twitter的业务开发副总Kevin Thau明确表示,Twitter不是一个社交网络(SNS),而是新闻,是内容,是信息!大言不惭地说,这也是我最近刚刚领悟到的一点。
从半年前,就一直想着自己写一个Twitter客户端,但是不得不说,现在已经有非常多优秀的Twitter客户端了,从共享到免费都有,覆盖了各种平台,那如果我自己要写客户端的话,有什么特色值得用户们抛弃现有的那些客户端来转投这里呢。在这大半年的时间里,我根据自己对SNS的认识,以及自己需求,不断调整心目中的客户端的特性需求,到现在才在心中有一个相对比较固定的框架、模型。
为什么FlipBoard会受到如此热烈的追捧,这就说明对于很大一部分人来说,使用Facebook和Twitter主要并不是为了与人交互和玩游戏,而是为了获取信息,而FlipBoard这种经过整理,同时又有美观排版的方式,很能迎合那些主要为了从网络获取信息的用户的需求。
处于Twitter中文圈中,比较容易忽视的一点是,将Twitter当成一个公共聊天室。当然这也是很大一部分人使用Twitter的目的,传统的网络聊天室的没落,使得用户们不得不将这种需求搬到其他形式的网络服务中,可以看到在各种BBS、论坛、IM群等等都有这种版聊的现象,所以在Twitter中存在这种现象也是正常而且合理的。只不过,从服务提供商的角度讲,应该可以从服务器端,甚至客户端提供这样的信息过滤、隔离的功能,用户可以方便地在两种应用模式间来回切换,想版聊就版聊,想读新闻就读新闻。除了FlipBoard,http://paper.li/也提供了类似的服务,但它目前只能说,这种模式还不错,各种细节方面还很不够。
再扯远一点说,现在很多人应该喜欢使用Google Reader这个服务,但说实话,Google Reader这个界面仍然有很大的改进空间。之前网上一直有人在号召大家使用RSS全文输出,但全文输出后有一个很大的问题是,在Google Reader中如果是全部展开的阅读方式,花费很多时间在拖动滚动条过滤无兴趣的条目上,实际上对于订阅了大量内容的人来说,很多内容只要一眼看到标题,或者其中的某张插图,就没必要看正文了,那现在Google Reader这种阅读方式就显得很落后了。而有一家第三方的Google Reader同步服务在这方面做了不少努力和改进,那就是Feedly。Feedly自己也提供经过分类的新闻内容,但对Google Reader中文用户来说,更有价值的是它的同步Google Reader的功能,可以提取出条目的标题和插图以及正文摘要,并以一定的热度排版,并连接了几家最流行的SNS服务,可以及时分享自己的条目,自从用了Feedly后,我几乎就不用Google Reader的官方界面了(喂喂,你是他们的托儿啊)。
再说回Twitter客户端,目前现在的客户端,基本上都是简单地通过Twitter API将Twitter的Tweet功能从Web搬到桌面或手机端等,几乎没有做更多的需求挖掘。简单地看过几十个完成度较高的Twitter客户端,目前只看到Seesmic Look收集了几组全球知名媒体的账号,但也仅仅是收集,没有更多的特性拓展。现在Twitter推出了新版界面,可以说是诠释了Twitter自己的发展理念,引领了客户端发展的方向──它提供的是新闻,是内容,是信息!
最后可以得出,我想要的客户端,是融合了FlipBoard、http://paper.li/和Feedly几者特色的客户端。它一方面可以向用户提供类似传统书报媒体提供给用户的视觉感观享受,另一方面则是结合网络、计算机的优势,提供大容量、快捷的信息分享功能。所以它不应该只像FlipBoard、http://paper.li/和Feedly它们一样只有一两家内容提供商,它应该是彻底开放的,允许其他内容提供商以固定的接口接入并提供特有的信息。而且它应该有一定的信息自动分类和索引能力,过滤重复或无价值信息,减少用户浪费的时间。
Tag Qt
不要使用Qt安装器中提供的CMake,而是自己另外安装一份,比如从CMake官网下载,或者macOS上可使用Homebrew在线安装。
鉴于最近买了个梯子,不大稳定,速度也没以前的快,直接打开在线的开发文档就感觉不大舒服了,想在本地弄个快的。今天编译试用了一下Zeal,感觉不错,比当时刚出来的时候好多了,不会随便动两下就遇到奇怪的bug,界面也不那么丑了。
突然想试一下CLion上写Qt5程序是什么体验,反正有JB家的全家桶License。CLion使用cmake作为构建工具,而Qt官方也开始支持cmake,但使用过程中还是遇到一些坑,记录一下。
总共花了十几个小时用Qt写了一个简单的、具有图形用户界面的、CoreDNS配置文件生成工具,只有一个主窗口,传统widget比较丑:
这个app在2014年就上架过,除了一开始送出去一堆兑换码以外,以每月大约不到1个付费用户的速度卖出过几份。后来也就更新过1个版本,后来就懒得更新了,直到2017年10月因长期不更新被下架了。
这是好几年前就开的坑,当年是对标Launchy,后来推翻重写,想对标Alfred,到目前为止,也仅仅是完成了很少几个功能,很多精力和时间都花在UI上了。一开始是照Launchy的完全图片自绘,最近加上了Alfred风格的UI。
之前已经在Windows上用clang编译Qt程序,但当时的Qt Creator并没有好好地支持,所以需要在控制台上直接使用命令行进行编译。今天偶然发现最新的Qt Creator已经支持clang-cl套件了,试了一下效果不错。
大约一年半前因为感觉遇到解决不了的技术问题,于是imchenwen的坑就扔下不管了。上个月的时候突然意识到,妹子喜欢看网卡的视频,优酷腾讯芒果爱奇艺等等,但是因为身体原因捧着个手机或iPad看会觉得头疼,看电视就要好很多,所以就萌生了在电视机上看网络视频的想法。
几年前也曾经试图折腾过Clang on Windows,那时候的完成度还不高,只能配合MinGW使用,而且头文件搜索路径还是源代码中硬编码的。
最近这段时间都在写一个叫UMLGen的GUI程序,从名字可以看出,就是一个用来画UML图的工具,与大多数现有的WYSIWYG(所见即所得)的UML画图工具(比如Visio,StarUML等等)不同的是,UMLGen使用代码的形式来描述UML图的呈现,与LaTeX的思想类似,即WYTIWYG(What You Think Is What You Get,所想即所得),我个人认为这种方式特别适合程序员使用。现在可用性已经很好了,主窗口截图如下:
最近又要在一个Qt程序中解压缩一些zip文件,以前用过QuaZIP,总觉得如果能不引入一个额外的第三方库会更舒服一些,于是上网搜了一下,还真有办法!
Qt在Windows上支持众多编译器套件/版本,图省事可以直接从msys2的仓库通过pacman安装,有32位和64位,静态链接和动态链接总共4个包。还可以通过pacman安装Qt Creator,也有32位和64位共2个版本。经过简单试用下来发现,从msys2安装的Qt与从官网下载安装的MinGW版本Qt基本相同,但比MSVC版本要不好用些,我遇到几个问题不能解决:
imchenwen的进展不快,这段时间主要在做两件事:
不知道怎么想的,突然开了个新坑,因为bilibili mac client并不能好好地工作,所以自己写一个也挺好玩的。
今天手头上的Nexus 6通过OTA升级到了Android 7,之后发现几个用Qt写的App显示中文字符全变成方块了。这个问题在当时系统刚升级到6.0时也遇到过,解决办法是自己带一个中文字体,再在程序中指定使用这个中文字体。这是比较繁琐的解决方法,Qt官方也收到了问题报告,只不过修正后的版本还没有发布,但是问题报告下面有人提到了问题代码,所以要自己出个workaround也很容易,只要在自己的程序开头加这么一段代码就可以了:
最近想着赶紧弄个程序出来上架到Mac App Store去,因为我只会用Qt写Mac的GUI程序,所以要研究一下如何把Qt程序签名上架,结合网上找到的这篇、这篇,以及这篇文章,折腾了几天了,最终,仍然没搞定怎么签能上架Mac App Store的Qt程序,貌似只搞定了Developer ID类型的,即在Mac App Store以外发布的程序,这种签名唯一的用处貌似是别人拿去能直接运行而不会弹出个消息框说来自不受信任的开发者(其实我是猜的,没验证过。
仍然是日志查看程序,突然想要加个按正则表达式的查询,记得sqlite是支持REGEXP的,不过sqlite官方文档上说了,需要程序自己提供一个进行正则匹配的函数,然后调用sqlite3_create_function来实现。
这几天写了个查看日志的程序,日志是公司里产品项目用户log4cxx生成的,用于定位问题。以前看到过其他同事自己开发的这类程序,但都只限于他们自己使用,等他们离职了,就基本失传了,尽管他们是交接给其他同事了。
在高中同学的公司里兼了个职,原本只说是提供技术部发展等方面的咨询和顾问等事宜的,于是我要的兼职报酬也不高。后来他说要我写个程序,做债权匹配管理,我就觉得有点坑爹了,我顺势就提要求配一个笔记本,虽然是最低配的。一直拖拖拖,一方面是确实拖延症严重,另一方面也确实觉得这东西应该工作量不大。后来做的时候发现还是有些折腾的地方的。
之前写过一篇文章谈到为Android app设置splash screen,以避免Qt写的app启动时有一段时间黑屏。今天收到一位朋友的email询问,在splash screen之前仍然会有一个黑屏,怎么去除。
Qt for Mobile默认是用了一张纯黑的图片作为程序启动图片,所以一开始程序启动时会出现1到几秒的黑屏,机器越慢,这个时间越长,比较不美观,我们可以自己动手设置上适合的图片。
昨天突然又想在Qt for Mobile中用上Boost,于是先得把Boost编译到iOS/Android上,然后发现了一个叫CrystaX NDK的东西,它本身的可以作为官方Android NDK的替代,不但对标准库和编译器有了一些改进,还包含了预编译好的Boost库。
前些天想着给istkani在Android集成个push notification,用了腾讯的信鸽,结果在进程退出后老是会弹框说进程意外结束云云,于是就放下了。
先看一遍Apple的官方文档或者网上随便找个入门介绍文章,知道代码主要要做的是在AppDelegate里开头做点初始化工作,然后实现几个函数。Qt对各个平台底层都做了良好的抽象和封装,好在有人做过些相关的研究,可以自己写个AppDelegate替换掉原来的那个。那块代码抄过来后,要注意的是因为我们替换原有的AppDelegate已经过了didFinishLaunchingWithOptions的时机,所以我们在自己的AppDelegate里写一些初始化的代码在didFinishLaunchingWithOptions里是没用的,我的办法是在替换AppDelegate后再做那些初始化工作。但是另外带来些问题,原来写在didFinishLaunchingWithOptions里的一些代码是可以work的,写到其他地方时可能就直接crash了,比如以下这些代码:
这两天看论坛,又想到两个对我来说比较有用的东西。其中一个是密码管理。
QtQuickCompiler出来有一些日子了,自从istkani在iOS App Store上架后,就没怎么关心过Qt的进展,只是差不多每天例行扫一遍Qt的邮件列表而已。昨天心血来潮想试试QtQuickCompiler到底有多神,首先快速浏览了一下官方文档,发现使用还是很简单的,然后开始照文档的说明一步一步操作。
春节放假时有一天突然想到Qt是支持用Intel C++编译的,有icc的mkspec,而且Intel C++在Windows、Mac和Linux都有,还能生成32位和64位的可执行文件,于是就想试一下,如果确实可行,以后就不用GCC了,虽然GCC也很好。
比较囧的是,在Windows上,Intel C++除了最核心的编译器,其他的都是用Visual C++的,比如运行时,甚至包括nmake,于是很不幸的是nmake貌似不能通过命令行参数指定并行编译,只能单线程编译了,纠结。
自己编译Qt的话,Windows和Linux都要为32位和64位系统分别编译,Mac倒是只要编译一个就行了,但是有个小问题是上次在Mac OS X 10.6.7上编译Qt 4.8.0时64位版本到后面有个什么库没有,于是只能编译32位版本了,囧。
今天彻底打酱油了,我们shared dev team也只剩下我,老大和Jason三个人了。因为晚上2点才睡,才睡了不到6个小时,于是下午就坐在办公椅上睡了近1个半小时,最后是被他们讨论一个bug的声音吵醒的,啊哈哈,老大还说让我看一下,现在只有我在这方面有经验了,我囧,我完全没经验的说,后来还是Sherman厉害啊! 再后来,就跟老大讨论了一会儿C++ singleton的实现,以及跨DLL数据引用等等。问题是有个Watson的bug,我从一次crash的call stack中发现,程序在调用_exit后,该程序中的static object应该是已经瞬间被无声息地干掉了,所谓无声息的,就是说,连它的析构函数都没被调用的。但这时嵌入的CLR还需要做一部分扫尾的工作,而恰恰是这扫尾工作又反过来调用了那个貌似已经被干掉的static object,于是程序crash了。当然这只是我的猜测,我猜测嵌入的CLR就是要生存周期长一点,于是一直在代码中试图找一下它是怎么从C++端嵌入CLR的,然后怎么用CLR的。我发现的情况貌似是这样的,先用Managed C++写了一个dll,这个dll可以在DllMain,还可以导出函数,而据我前些天才知道的知识,.NET编写的普通的DLL形式的assembly跟原本的DLL不一样,没有DllMain的。而这个DLL通过导出函数返回一个对象的指针,这个exe程序通过GetProcAddress获取导出函数,再调用这导出函数获取对象指针。这个返回的对象呢,是个CLR Bridge,也就是说,通过这个对象,可以从C++端创建CLR中的对象,调用CLR对象中的方法等等。也就是说,从代码中,我没看到Jeffray Richter在《CLR via C#》中说的那种CLR host的方法。现在我仍然在怀疑,是不是我代码没看全,但我确实之前也在整个代码目录下搜索文本,没有那几个用于host CLR的API调用。似乎有点跑题了。然后我就跟老大说了一下我发现的这些情况,略微讨论了一会儿,老大表示自己也不知道,唔,其实我也不指望他知道,只是有这么一种想跟人分享自己的发现的欲望而已。基本上,我就觉得这很可能是此bug的root cause了,但老大说可能只是个cause,而不是root cause,好吧,其实就是缺少验证而已。一个比较有说服力的验证方法是自己用C++写个小程序,然后用相同的方法调用CLR中的代码,最后能制造出同样的crash,只是我最近木有动力去做这些事而已。另外就是,即使确定了这是个root cause,简单地说来,这个root cause应该就是对象销毁的顺序不对,这是可以肯定的,但之后也不好fix,因为这个程序实在太庞大了,有很多对象,然后引用关系也很复杂,以我目前对它的了解程度,根本没能力对理顺这个关系,于是也就fix不了了。而且还有个另外的问题是,那个static object是该程序中用于实现singleton的一种方式,我觉得比较奇怪,老大说,这是为了应付多线程的情况。还有种应用多线程的singleton实现方式是在create instance时加锁,唔。关于这个话题,在前段时间看到TopLanguage group中有个讨论,提到boost中某个库中的singleton实现,貌似很干净的实现,不用锁,也不是static object,能适应多线程,囧,具体的不记得了,貌似boost中有好几个子库中都有自己的singleton的实现,得再去看看代码才行,另外好像《Modern C++ Design》里也有对多线程singleton实现的讨论,春节放假看看去。 话说,今天还看到Mono,发现除了有Mono Touch外还有Mono for Android,不过免费试用版都只能在emulator上跑,最便宜的个人版license也要399刀。不禁大骂Qt的不给力,为毛只能为Symbian和MeeGo用,Android port至今还在alpha...
N9作为Nokia推出的唯一一部装载MeeGo系统的手机,主打宣传的是其滑动手势。
滑动手势在其他触摸屏设备上已经有所应用,各种移动操作系统也对其有一定的支持,但在N9上作为主推特性的滑动手势主要是基于Qt这个跨平台的开发框架实现的,因为从实现角度讲,N9装载的MeeGo系统的UI都是建立在Qt的基础之上的。
Qt自从被Nokia收购后,一直致力于在移动设备上的移植工作,尤其是对Symbian的支持越来越多。而MeeGo这个原本由Nokia和Intel合作开发的项目,同样做了很多跟Qt适配的工作。
Qt做了很多为方便实现触摸操作响应的工作,特别是后来推出的Qt Quick,彻底地让UI和业务逻辑分享。美工可以只使用非常简单的脱胎于JavaScript的声明式语言QML来构建UI,而程序员则可以专注于使用C++或JavaScript实现底层的业务逻辑。Nokia为QML提供了非常丰富的UI元素,还为Symbian系统特地实现了一组扩展的UI控件,这已经可以实现绝大多数的UI需求,各种UI元素又可以随意组合从而构建出更加复杂的应用。而且Qt还提供了多种QML与C++交互的机制,如果QML内建的UI元素不能满足实际需求,程序员可以用C++实现复杂的UI,而Qt本身又有基于CSS style sheet的UI方案和Graphics View的方案,这都让开发人员可以快速地制作出炫目的UI来。另外值得一提的是,基本上可见的QML UI元素,都为触摸操作甚至滑动手势提供了一定的支持,这从QML自带的Demo就可以看出来,不但需要的代码量非常少,而且做出的UI效果却非常时尚。
可以这么说,Qt推出Qt Quick这个方案,代表了应用程序开发的一个方向,快速制作精美UI的方向。基本上所有大的开发框架/解决方案都采用了类似的技术,比如微软的WPF,Mozilla的XUL,甚至Qt在开源界的长期竞争对手Gtk+也有类似的方案,即用简单的标记式、声明式的语言构建UI,减少美工们的学习负担和工作量,而使用其他功能强大、便于操控底层的语言实现业务逻辑。相比其他几个竞争对手,整体而言Qt的优势在于跨平台性好,配套的开发工具也一直在进步。但是它必然也有些缺点,比如一直以来Qt的运行效率不高,虽然Nokia收购后这在方面做了大量的努力;前不久Qt又回归了社区,Nokia成为了一个普通的贡献者,这也许会带来发展方向模糊,进度缓慢的问题,比如一直由开源社区在开发的Qt for Android的port,一年多了仍然没能正式发布。
总的说来,Qt是一个构建Windows、Linux、Mac OS X以及Symbian、MeeGo应用的低成本、高效率的解决方案。如果基于lighthouse机制的Android和iOS移植能尽快正式发布,那在普通消费型电子产品平台上,就真的如它的宣传语所说的Code Less, Create More, Deploy Everywhere了!
作为纸醉金迷的生活的开始,随便在网上看了一下上海的景点列表,排在第一位的居然是上海科技馆,恰好我也知道它在某条地铁线上,于是就跑过去了。之前就听别人说过不好玩,去了之后才体会到到底不好玩到什么程度。60块门票实在太不划算了,6块钱才差不多。里面多数是小孩,以及带小孩子来的大人,像我这样的实在很稀奇。封杀之~
今天在公司里把AWD的第一部分快速过了一遍,明天继续看第二部分,争取这周把整本书都过一遍,达到可以用windbg完成基本的调试任务的目标。说到底,最终的目标是要能用windbg分析dump file的目的,虽然以前也做过这种事,但都是囫囵吞枣不求甚解的,这次有机会可以系统的学习下很有用。另外,我想在这公司里,估计以后回过头来看,最大的收获可能是英语的听读能力有大进步吧,可能写和说的能力也会有所提高吧,这将是我最高兴的事。
周末无聊,随便算了一下自己每月的固定开销,吓了一跳,居然这么高,这点工资收入实在不够看,要多久才能攒够买MBP的钱呢,昨天从上海科技馆出来后跑到陆家嘴的苹果专卖店,发现13寸的那款只要11498了,以前印象中是13998的呀,好心动,国庆后一定要入一个。也就是说,光靠这点工资的收入是远远不能支撑我日益膨胀的消费能力和消费欲望了,赚外快呀呀~
csdn上的Qt应用开发大赛奖品好少,不过E7很让我眼馋喵,还剩下一个半月,快速写几个程序试一把。先就已经提上计划好些日子的Aokiwen吧,豆瓣客户端,支持Win/Mac/Linux,以及Symbian。qDou其实已经做得不错了,不过它一开始就是为手机设计的,有些方面不是很舒服。握拳!
今天突然在推上看到Nokia N9的消息。搭载了MeeGo 1.2版本,已经很新了。
下午收到了Qt Ambassador的邮件,邀请为N9开发app,还可以申请N950用于调试和测试。可以使用Qt为N9开发应用,对我来说,实在是欣喜,至少Ninayan要移植过去应该障碍很少了。
上官网看了一下大概的情况,官方指导价550欧,有点贵,不过它有3.9英吋的屏幕,而且看截图,真的有点心动。
感觉N9会是一个好玩具。
实在有点不乐意做Deardawn,心理障碍克服不了啊。
Ninayan今天被小言一说,才发现真的是添加不了账号了,原来是之前一次为了加快启动速度的修改,把其他功能破坏掉了,不但添加不上账号,还一开始不能发布消息,只有在显示过home timeline后才可以。
提取了几个model类,这样的实现比较优雅。
几个singleton在程序退出时都正确销毁了。
把AutoProxy的gfwlist信息配置保存到sqlite数据库里了,可以记录每条规则的enable与否,hit次数。在每次程序退出时刷新这些信息到sqlite数据库里。
给几个本地数据库建了几个索引,这样可以让查询速度加快一点点吧。
由于占用内存比较厉害,在Windows下就用::EmptyWorkingSet每分钟清空一次工作集,其他平台不知道有什么类似的方案。但实际上在Windows下如果窗口最小化时,内存会被一下子回收好多,不知道到底是怎么回事的。
本地数据库读写冲突的问题还没想到比较低成本的解决方案,叹气。
停下来想想,现在已经实现的功能也只是玩玩而已,最有用的应该还是Google Reader支持吧,可惜没找到确认无误的API文档。
blog被墙了就真不太想更新了。
Ninayan这段时间除了不时地发现些bug,然后修正外,主要是增加了对163、Sina、Sohu、QQ微博的支持。从开发者角度讲,163的API是最接近Twitter了,QQ的API设计最山寨,完全自己搞了一套,Sina和Sohu从技术角度讲跟QQ接近,接口设计仍然是模仿Twitter。
然后在google code上放了Linux版的可执行文件上去,今天才知道原来各发行版上普通的应用程序是可以做到二进制兼容的,也怪我以前看CodeLite、Code::Blocks它们都为每个发行版提供一个独立的安装包,就先入为主地以为每个发行版都要各自单独编译才行。今天突然想到Qt Creator就是同一个可执行文件在所有Linux发行版里可以运行,只是区分了32位和64位而已。我还傻乎乎地在12个系统里都编译了一把Qt,再分别编译出Ninayan,再分别打包,再分别上传,天呐!
首先一件很郁闷的事,貌似域名被墙了,直接用IP是可以打开本blog的,但是我暂时又不想去折腾这些了,先这么放着吧,问候下方校长18代祖宗及全体女性家属。
Ninayan最近动作倒是不大了,主要是先打了Mac,Win32和Linux的安装包给几个人试用了一下,结果反响很差,有点失落,难道真的定位有问题?
不过说起来,Ninayan现在也只是个雏形,真正的主要的理念需要的特性并没有实现,现在也只是把图片,视频和文章链接单独提取出来可以独立浏览而已,并没有做进一步的工作,比如要能打tag,可以检索,自动语义过滤,优先级排序等等。其次是RSS聚合也没做,Google Reader没实现,UI缺少专业的美工设计等等,总之可以做的工作还有很多很多。
另外,今天勉强让Ninayan在我的Nokia 5230上运行起来了,解决了不少问题,但最终还是由于报内存不足而自动退出。为了让Ninayan可以在5230上运行,遇到了不少问题。首先是开发环境的建立,我用的是Qt SDK 1.1 beta,这个SDK用的是Qt 4.7.2,但有bug,for S60v5的配置文件使用了for Symbian^3的配置,所以编译工程的时候会出错,要自己在工程的.pro里把opengl的配置去掉。其次是部署时,要安装Qt,还要单独安装sqlite,据说以前版本是合在一个安装包里的。最后是这两天一直在纠结的问题,运行后在TextInput获取输入焦点后,虚拟键盘没有显示出来,在Nokia的论坛和Stackoverflow上问,都没人回复,今天偶然想起qDou,试了下它在5230上至少是可以输入文字的,虽然之后会崩溃,于是发邮件问了一下作者,作者给了个网址,原来是我在TextInput控件一起放了个兄弟控件MouseArea,于是TextInput没能收到点击事件,于是虚拟键盘不会自动显示,只要自己强制调用它的openSoftwareInputPanel方法就可以了。
至于最后的自动退出,从现象结合网上的人们的讨论来看,似乎是因为同时请求的网络连接太多,以及内存占用过多引起的。叹气,桌面程序写惯了,散漫惯了,都不怎么注意内存的使用了,反而经常采取以空间换时间的策略,看来如果真要让Ninayan能在手机上正常跑起来的话,还得好好重新设计一下,把各种请求都放进队列里,不要一下并发几十个连接,其他的内存使用策略也得仔细看看,有点想看看侯捷翻译的那本讲内存受限系统的程序开发的书了。
Ninayan的主要功能基本上都做出来了,剩下的主要是增加各种服务的支持,比如各种微博,各种SNS,以及Google Reader。其次便是界面和操作上的细节方面的调整,现在还是很粗糙的。
离上次W.I.P.已经有3周多了,这3周主要实现了文章浏览特性。文章浏览有3种模式,一种是仿feedly的可扩展的列表,一种是信reeder的分栏,还有一种是仿paper.li的报纸模式。但是,目前的效果还远远没达到预期。放几张图吧:
还增加了个视频观看视图,这是计划外的,但觉得有必要,也很粗糙:
直到这里才发现,在Mac OS X 10.6.6上一直以64位Cocoa编译的Qt,果然视频播放不了了,不记得在哪里看到过说明,QtWebKit在Mac上如果是64位的话是载入不了Flash播放插件的,因为Flash播放器稳定发布只有32位版本,于是在Mac上也自己编译了一把Qt,改成32位Cocoa框架的就可以了播放视频了,太纠结了,也难怪乔帮主要封杀Flash了。
今天觉得Ninayan大部分功能已经实现了,也差不多快可以发布beta版了,于是要打包,先解决Windows和Mac上的打包问题。 Windows上一直以来我都习惯用Inno Setup了,所以在如何制作安装包的问题上并不纠结,InnoIDE和ISTool都是很方便的工具,主要的问题在于解决Qt的插件的部署。Ninayan在Windows上也是用GCC(MinGW)编译的,相比VS2008,少了个SxS的问题,只要带两个dll一起发布就行了。Qt本身有一种简单但比较有用的插件机制,它的字符编码支持CJK,图形文件格式支持,数据库驱动等等都是由插件实现的。也就是说$(QTDIR)/plugins下的东西都要跟着发布,而且程序代码中需要自己在main()中,app对象创建后及时调用QCoreApplication::addLibraryPath()添加plugins的路径。另外由于用到了QtWebKit和QML,QDeclarativeEngine对象也需要指定一下qmlwebkitplugin插件的目录,把$(QTDIR)/imports/QtWebKit目录打包进去,然后在代码中调用QDeclarativeEngine::addImportPath()添加路径,这样整个目录就是发布的所有内容了。 在Mac OSX上比较流行用dmg,但这之前还要解决Qt的framework链接的问题。Qt在Mac OSX下官方发布的二进制包是framework形式的,这跟Windows下有点不同,呃,其实跟SxS有点类似。要用install_name_tool -change命令行修改自己的程序可执行文件链接的framework的位置,这个工作可以由Qt自带的一个叫macdeployqt的小工具完成,只要在命令行执行macdeployqt Ninayan.app就可以了。不过除此之外,还是由于qmlwebkitplugin的缘故,需要自己复制这个插件到程序的bundle中,我就放在跟最终的可执行文件相同的目录中,这个插件macdeployqt并不处理,除了要自己复制,还要自己用install_name_tool来修改链接的framework。这样操作后,是一个可以正常运行的,完整的应用程序bundle,整个bundle就有113MB,谁让Qt那么大呢!然后是把这个bundle打包成dmg。Mac OSX自带免费的工具,GUI和CUI的都有,GUI的叫Disk Utility,不过看了下感觉界面挺复杂的,还是用命令行的hdiutil爽,而且我前面是用命令行修改的符号链接,这里当然最好也是用命令行打包,这样一个shell脚本就能搞定编译后生成dmg的所有事情了。用hdiutil的话,这个命令行就可以打出一个dmg来: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDZO -ov Ninayan.dmg 不过这个有点土,就是把Ninayan.app放成了dmg而已,其他什么都没有。我的要求其实也很简单,有自定义的背景图片,有Applications目录的链接,这样用户打开这个dmg就可以完成把Ninayan拖拽到Applications目录中的操作。在网上找了不少文章和视频,多是用其他的GUI工具,在stackoverflow上有个家伙用AppleScript写了段脚本,确实通用性和灵活性都比较好了。最后我选了条简易简陋没通用性的路子,但够用。首先需要明白的是,dmg被Finder打开后,就是当成一个普通的文件夹处理的,所以它的背景什么的设置,都是放在.DS_Store文件中的(Mac中以dot开头的文件都会自动隐藏),所以很dirty的做法是,先用这个命令行创建一个可读可写的dmg并挂载: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDRW -size...
已经不记得有几个大年三十的晚上是在电脑前写代码度过了,今年破天荒的因为客厅里电视在放春晚,打偶然走过去看几眼。
今天把超链接处理模块重构了,之前那个实现在Mac下崩溃得比较频繁,但在Windows和Linux下却不是很多。对于这个现象我有点疑惑,虽然说代码确实是写得有问题,但为什么只有在Mac才比较明显呢。好在Mac下崩溃了打印出来的栈回调信息比较详细,几乎能跟踪到最终引起崩溃的代码行。
原来的实现把所有中间数据结构以指针的形式保存在一个list里,然后在自认为结束的时候销毁对象。这样的做法本没有什么问题,关键是我在操作这个list时并没有考虑重入的情况。于是重构主要做了两个重大修改,一是在list中直接保存对象,而不是指针,这样更不容易写错;二是对list操作大部分情况下都加mutex锁住。顺便也修正了些其他的小问题,比如原来即使是基于embed.ly的服务识别url是图片还是视频也有问题,其实embed.ly是返回了这个类型的。
另外,今天还把主界面针对360*640分辨率修改了一下,因为Nokia的S60v5和Symbian^3现在几个机型都是用这个分辨率的。至此,图片浏览特性的实现暂时告一段落,接下来该实现文章阅读了。昨天大致研究了一下Readability,发现它在Firefox表现那么风骚,结果在QtWebkit下总是返回不能分析的错误。不知道是DOM树的实现还是JavaScript引擎的问题。难道真要我移植一个C++版本,这实在太费时费力,还不好维护了。
最后,上个最新界面截图。
终于勉强加上了一个功能比较凑合的图片浏览功能,还有很多地方需要改善。本来我的想法是UI上直接拿QML Demo PhotoViewer的代码来用的,可是昨天发现PhotoViewer中的代码会导致在Windows下程序不能切换输入法,于是只好自己写了。自己写就极大地简化了功能,才简化了代码,于是最后所有东西都放在一个QML文件中写完了,最终的效果,也就是几个视图场景切换时那个动画效果没有了。残念!
另外有个问题是图片下载的问题,现在的Twitter上比较流行的图床大多是被墙的,如果让QML的引擎自己通过代理下载图片,感觉不是一般的慢!所以我就觉得把这些图片事先下载到本地缓存起来似乎挺有必要的。
还有个比较重要的问题是全屏模式下浏览图片,默认是自动拉伸到整个显示区了,这样似乎比较影响显示性能,当然也是机器配置不是那么好的才会有这种卡的情况,在我的T43上会卡,拿到Mac mini上就流畅了。应该稍微改一下,看一下是不是在加载前就获取图片本身的尺寸,如果比显示区域大,才缩放,不大的话,就以图片本身的大小显示了,这样显示也更清晰点。
还有个浏览某张图片的大图就不截了,没啥好看的。
有些问题,总是那么奇怪。因为XP里的虚拟机在跑Debian编译Qt,于是在Mac下把QML的Demo PhotoView抠过来用,本来就很吃力,还顺带发现了一个因为先后顺序问题引起的崩溃bug,终于可以在Ninayan里看到PhotoView的样子了。可是到了晚上突然发现,在Windows下不能切换输入法了,一切换Ninayan就挂死!经过一部分一部分地屏蔽代码发现,引起这个问题的似乎是VirtualDataModel中Package的一些代码。好吧,决定索性不用抠别人的代码,用自己的方法写一遍相同的UI吧。
上一段提到,我又蛋疼地在Debian里编译Qt了,嗯,又花了一下午。之后就是编译Ninayan,呃,我现在最大的乐趣就在于在不同的系统里编译Ninayan并用它来上Twitter了,囧rz。想来也不会有多大问题,毕竟之前在Arch和Mint里都比较顺利的,唯一大的区别是在Arch和Mint里桌面都是用Gnome,而这次Debian里用的是KDE,很花哨的感觉。言归正传,Ninayan运行得很顺利,除了字体不太好看。在Twitter上报怨了一下后,@truthurt建议自带一个开源的字体,真是个不错的主意,在Mint里的那种就很好,我后来去网上找了文泉驿的微米黑,在Debian和Arch里效果都很好。其实昨天就想过字体的问题,不过当时想到的是直接将字体装入到系统中,然后在程序中直接通过字体family名使用。今天偶然想到,其实可以程序直接载入指定路径的字体文件来使用的!不过Windows下还是用微软雅黑吧,微米黑在XP下同一个字的不同笔画都有粗细差异,真糟糕。
今天照计划,实现了查看对话的功能,不过不完善,因为网络传输的原因,是一条消息一条消息从服务器获取后显示,如果显示到一半切断,又要显示另一组对话,就会把前一组对话后面没显示的那些消息作为后一组对话的消息。所以要考虑一下怎么加一个中断的机制,不过这个留到以后版本中完善吧,毕竟Ninayan一开始定位就不是一个完善的客户端。
然后又蛋疼地去装ArchLinux了。这个发行版安装比Ubuntu麻烦多了,它的iso镜像只装一个最基本的字符界面,然后带一个pacman包管理工具,GNOME之类的桌面需要自己再另外安装,所以最好有比较畅通的网络。
装完后,中文字体的显示惨不忍睹,google随便搜了一下,也挺折腾的,我懒得弄了。我就是想在上面试试编译Ninayan。没想到可以用pacman安装已经编译好的Qt 4.7.1,再装个Qt Creator,就可以编译Ninayan了。除了显示的字体不好外,其他的还算凑合吧。
明天开始做图片浏览和文章阅读功能吧。
昨天和前天晚上蛋疼地在Linux上编译Ninayan了。我用的是Mint9,也就是一个Ubuntu的修改版。在Linux上编译Qt程序有点麻烦的是需要自己编译一遍Qt,前天晚上就编译了一遍最新的qt-everywhere-opensource-src-4.7.1.tar.gz,过程比较顺利,再装上Qt Creator就可以编译出Ninayan了,简单试用了一下,很正常。而且令我比较惊讶的是,我学Hotot用了Droid Sans字体,最终的显示效果在我个人看来比Windows XP SP3和Mac OS 10.6.6上都要好,但XP SP3上加上Gdipp或MacType后,效果会有很大的提升。
昨天突然发现,Ninayan在Mint下不能访问https://api.twitter.com(不是被墙的缘故),测试了几次才确认是不能访问https的地址,于是想到前不久看过一篇博文说Qt 4.7是有这么个bug不能访问https的,因为原来Qt 4.6带了SSL证书,而Qt 4.7没带,于是照那篇文章的作者的说法,从Qt 4.6.2里找到qt-ca-bundle.crt文件,然后每次QNetworkRequest在被post或get前都设置一下Ssl证书。结果我的情况是连编译都不通过,于是可以确认是Qt在编译时没有编译进OpenSSL了。然后找到了这篇《Compile Qt 4.7 on Ubuntu 10.10》,先要安装一堆的库的开发包,再来编译Qt,最后再编译Ninayan,果然就正常了!于是我就不明白那篇博文讲述的到底是个神马问题了!
今天就比较烦躁地在做网址缩短功能了。本来打算内置goo.gl,bit.ly和is.gd三个短网址服务,结果很郁闷的是bit.ly总是返回INVALID_URI,但同样的URL我拿到Firefox下测试就能返回正确的数据,这不是歧视嘛,难道是在http header里还要设置神马东西?倒是goo.gl和is.gd都正常了!
话说前天偶然发现了MacType和Gdipp,觉得这种功能对Ninayan之类偏阅读的应用非常有帮助,于是我在极限论坛上给MacType的作者私下发了个email询问是否可以提供专门的API以便集成此功能。不过到现在也没收到回应,估计是不愿意了。
今天看了一下MacType的安装目录,发现有个MacLoader.exe,而Gdipp的安装目录下也有个loader文件,这时才明白过来,可以通过把可执行文件的完整路径作为命令行参数传递给这loader,那么该可执行文件会被启动运行,并被注入实现字体渲染增强效果。
经过简单的测试,Ninayan在我的XP SP3上使用微软雅黑字体,加上增强字体渲染效果,感觉确实更舒服了!而Gdipp是以GPLv3,最新的版本好像是用LGPL了,一起打包发布应该是木有问题的。我只要另外再写一个小小的启动程序,在安装包中把启动程序作为快捷方式添加到开始菜单和桌面等位置,可以自己调整是否使用增强字体渲染效果,使用什么样的渲染配置等等。
这样一来,似乎Windows上的效果都超过Mac上的了,一直没找到感觉特别好的Mac上的用于大段文字阅读的字体,微软雅黑只适合在Windows上用,而且至少要开了ClearType Tuner才行,有MacType或Gdipp最好。也许是因为我在Mac下用的是CRT的显示器的缘故,不止一个人对我说过那个视频信号转换后损失挺大的,也许用LCD的就要好些了!
今天心情不错,呼呼!
前面说到内存泄漏的问题。后来通过逐段屏蔽代码,终于找到了最大一处泄漏源。这个办法比较笨,但这次真的有用,主要还是因为程序结构简单,流程也不复杂才能用吧。
程序大体上分为三部分,UI层,数据层,网络通信层。用户在UI层上操作,1、UI层向数据层请求数据,2、数据层根据不同情况直接查询本地数据库或通过网络通信层获取数据,3、网络通信层自己有一个定时轮循的任务,每分钟从远程服务器获取数据,4、有了数据就发送给数据层,5、数据层将数据经过简单处理发送给UI层,6、然后显示,就是这么简单。
我开始主要怀疑UI显示调用的Qt/QML也许MM有问题,于是把最终UI显示的代码屏蔽掉。发现仍然泄漏的情况基本没有变化,说明跟UI显示的关系不大。后来发现Mem Usage的增长是有周期,大概是1分钟1次,那么可以确定是在4和5两步有问题。这时把第5步中代码全部屏蔽掉,果然Mem Usage就不增长了。然后逐步缩小范围,一点点放出代码,最后发现竟然是QSqlQuery查询本地数据库时,select出来的东西需要程序员自己clear掉!内牛满面啊,果然是Qt用得有问题!
今天偶然发现一个叫MacType的东东,可以在Windows下以进程注入的方式给指定进程增强字体渲染效果。跟微软官方的ClearType Tuner是一类东西,不过MacType的选项更丰富。于是我想到,我这个以阅读为主的工具,要是集成这么个美仑美奂的功能,该是多酷啊。在极限论坛翻了一遍帖子,貌似MacType是闭源的,另外有个新生的Gdipp项目,倒是在googlecode上开源了,不过听说它的配置复杂,而且目前不够稳定,尤其是32位系统上。好吧,反正这种功能对我有致命吸引力,一定要集成!
内存泄漏的问题,调得我心力交瘁,都有点神经衰弱了,甚至有点绝望,唉。以前还真没有过这种强烈的负面情绪出现过。
每次UI刷新,从任务管理器里看Mem Usage都会增加2-3MB,这得有多严重的泄漏啊!可是我自己的代码中new出来的对象都经过跟踪是销毁掉了的。于是又把矛头指向Qt内部,或者是QML中了。
本来怀疑是QML中的实现可能有问题,于是把Qt从4.7.0升级到4.7.1,貌似泄漏得更严重了。所以现在都已经不敢怀疑是Qt有问题了,开始怀疑是没有遵循Qt的用法。有些Qt返回的东西,需要程序员来负责销毁,比如QNetworkAccessManager在调用get或post后返回的QNetworkReply对象,这是多么操蛋的设计啊,指不定就是每次在哪里它自己创建出一堆对象出来要我来销毁我却不知道呢!
从CodeProject上下载了个Visual Leaks Detector,从说明上看,说是在msvc的jit debugger里会自动打印信息到debugging output window里的,可我实际上试了之后,发现屁都没输出一句,难道它是for MFC-based project only的?有可能的,唉!
简直走投无路了。
本来排除在计划外的事情,今天又去搞了,就是支持Twip4。前一天也折腾过一下,没弄好,这回问了一下Twip4的作者@yegle,他开始说是计算数字签名时用https://api.twitter.com/作为base string就行了。我试了下不行,后来他又说试试T模式吧,有几个客户端是经过实践T模式没问题的。于是一下子就明白过来了。 Twip4有T模式和O模式两种工作模式。T模式是完全的透明转发,Twip基本上不做任何处理,所以要请求oauth token和oauth token secret时原本是向https://api.twitter.com/oauth/access_token请求的,同时也是拿https://api.twitter.com/oauth/access_token作为base string计算数字签名的,在使用T模式的代理时,只要向http://www.myproxy.com/oauth/access_token请求就行了,仍然用https://api.twitter.com/oauth/access_token作为base string计算数字签名,这样就能无障碍获取oauth token和oauth token secret了。至于O模式,我看了下TweetDeck和Mixero的表现,发现它们也并不向O模式Twip请求oauth token和oauth token secret,或者请求了也没结果。所以我就推测其实O模式是没这功能的,O模式自己有consumer key和consumer secret,所以自己有一套oauth token和oauth token secret,但不是给客户端用的,即使客户端用自己有效的oauth token和oauth token secret发送给Twip请求,Twip也会把http header和url parameters里的东西处理一遍,用自己的那套oauth token和oauth token secret计算出来的东西替换掉。所以我想如果用O模式也要让用户可以无障碍认证的话,需要软件自己提供一个透明代理,软件先拿用户名和密码从那透明代理处获取oauth token和oauth token secret,然后在其他发布消息,收取消息时用O模式代理,就可以解决这个问题了。...
好吧,其实没做什么,本来的计划是先做图片浏览和文章阅读的,可是饭否上的内容实在太单薄了点,呃,这纯粹是借口,于是今天实现了对Twitter的支持。
昨天晚上弄到1点半才基本搞好怎么用xAuth认证获取oauth token和oauth token secret,今天就把twitter的timeline浏览,direct message浏览以及消息发布实现了。这内容比饭否丰富了许多,比如有了3列跟retweet有关的内容。twitter居然没有像饭否那样可以一次请求把foing和foer列表取下来,而只能先获取那些id,再由id去获取其他信息!于是这个功能就还没实现。还有比较影响使用的没实现的功能包括不能看conversation,不支持list,不能用快捷键操作。
不过有点值得欣慰的是,又修正了几处内存泄漏的问题。
今天就不上图了,因为基本上界面上没啥变化。
脑袋混沌了一天,终于基本上搞定超链接处理的功能了。
最开始是由于我使用的处理流程的关系,选择一个合适的数据结构让我头疼了好久,最后决定使用一个list,每个元素是一个结构体,每个结构体由两部分组织,一部分是URL列表,该列表会按短网址还原后的处理顺序存储URL,另一部分则是对该URL的描述,描述的字段包括当前是否已经完成全部的还原操作,最后一个URL能不能被embed.ly拆成两个新的URL列表,代表视频的html和html5等信息。
中间调试过程也是经历了重重磨难啊!其实也是自己代码写得有问题。一开始我是用一个map来存储url list和附着属性的,指针乱飘,调试得没有信心了,才改成上面描述的那个方案。还是有很多问题,经过层层排查,终于把所有的问题都找出来并解决掉了。甚至以为Qt的signal不能随便emit,会有对象生命周期相关的问题,最后也确认其实是在前面的代码写得有问题,哇哈哈!
明天就看一下怎么把数据库中的已有记录读取出来当历史记录来处理超链接。然后就可以做图片浏览的功能了!图片浏览功能完成后就做Readability的功能,之后再做twitter的支持,这就可以发布第一个版本了!
根据@zhangh109的建议,修改了一下界面,浏览文章有三种模式,在启动界面现在就只有一个入口Article View,在Article View中再添加切换浏览模式的入口。另外了加个图片浏览的视图,在启动界面中把原来About的入口替换掉了,About则移到原来的Quit按钮处。
URL处理部分今天还是没有搞定,不过思路清晰了很多,估计明天就可以完成总体的框架,到时候图片浏览部分应该就可以很快实现,而文章浏览部分需要把Readability的JavaScript代码移植过来,本来如果可以直接用它的那些JavaScript代码是最好的方案,可是之前我曾尝试过,不知道为什么内嵌的Webkit在装载完页面后,直接运行那个代码是没有作用的。所以干脆也不研究它了,直接移植成C++的,用Qt的接口操作Webkit的DOM树来解决吧。想来这移植工作需要花一些时间吧。
贴两张修改后的截图吧。
今天在处理超链接的问题,这是最重要的一环。
Ninayan提供给用户的信息分两大类:图片/视频和文章,微博消息只算是附属品。所以从微博消息中得到一个URL后,最终要能正确识别出它是一个图片/视频,还是一篇文章(当然,文章中也可以有图片和视频,但重点是它有文字),对于其他不可识别的类型,比如zip,则忽略。
我设计了如下的处理流程:
1、将URL与embed.ly可处理的类型用正则表达式匹配一下,如果可以匹配上,则用embed.ly处理,不能匹配上,则假设它是个短网址,将其还原成长网址。
2、embed.ly处理后,会返回缩略图和原图(如果是视频,则是一段HTML,可能还会有一段HTML5代码)的URL,假设这URL也是个短网址,也将其还原成长网址。
3、还原成长网址后,与原来的短网址比较,如果两者不相等,则假设该长网址仍然是个短网址,继续还原,如此循环迭代,直到还原失败或两者相等,最后还原的最终长网址与embed.ly可处理的类型用正则表达式匹配一下,如果可以匹配上,则用embed.ly处理。
4、如果第3步最终的长网址不能与embed.ly匹配上,则认为该网址是真正的最终应该由Ninayan处理的网址,可分为前面说的两类,图片/视频和文章。
至于怎么辨别出属于哪一类,我决定采用一个很粗糙的办法,如果前面经过embed.ly处理过的,那么肯定是图片/视频,或者URL最后是以诸如.jpg/.png/.gif等known的图片/视频文件扩展名结尾,那么也是图片/视频,其他的则都划入文章类型。而文章类型其实是个很粗糙的结果,网页是要经过像Readability那样的处理才是最终显示给用户的,而在Readability处理的过程中,可以过滤掉诸如.zip等不支持的文件类型的。
这个方案也只是考虑到了URL在网络交互上的处理过程。还有这处理结果怎么通知本地数据存储模块和UI显示模块,也是个问题。而这个问题涉及到何时通知,通知时采用什么数据结构,以及本地存储时采用什么数据结构。
添加了个图片本地缓存的功能,结果发现不是很好用。在Windows下实际使用时发现有时候装载本地文件仍然很慢,甚至不如直接从网络上加载的快。在Mac下发现压根就装载不上。初步估计是因为多处同时读写文件时有冲突,需要再仔细看看。
把删除消息,去fav后的响应也添加上了。
另外还有些细节方便的调整,比如所有显示图片的地方都添加了等待动画。
最后发现个奇怪的问题,在Mac下读取Friends列表有问题,json解析失败,这太诡异了。
今天听@shellexy说,用HTML5的话,配合JS/CSS这些东东,可以实现跨iOS/Android/WebOS/Symbian/MeeGo,呃,这也太强大了吧,而且据说Hotot移植到这些平台已经是在计划中了。得好好考察一番这种开发方案了。
昨天突然发现有内存泄漏,确实找到几次没有释放的,后来从任务管理器里看,貌似还有泄漏,但实在找不出有什么地方有问题了,最后今天把所有自己new和delete都放在一个类中统一调度跟踪,发现确实是都正确释放了的,只好先不管了。
今天搞定了显示friends和followers列表的功能,增加了显示所有自己发布的消息的功能。明天就搞一下显示之前的消息的功能。之后再修改一下消息显示的格式,比如图片预览,超链接处理等,然后就算是完成一个milestone了吧。
不多说,也是上两张图,还被@shellexy嘲笑了说~
经过一天的折腾,Ninayan已经能完成跟消息相关的绝大多数操作了,私信也搞定了。作为一个纯粹的微博客户端来说,也就剩下图片上传和用户Profile查看没做了。更多的诸如图片预览等功能属于比较有用的增值功能,不在这个范畴内。
汇报一下进度,Fanfou的API果然是最简单的,现在除了可以浏览时间线,回复线和收藏外,已经可以做些基本的操作了,比如发消息,当然包括回复,收藏和取消收藏,删除消息。而且也把消息都保存到本地了,每次切换页面时,显示消息的速度就相比以前会快一点,以前是每次都要从服务器上取下来才能显示。
接下来要解决的是,发布消息后刷新界面,以及消息中的超链接处理等细节问题。
今天折腾下来后,已经可以浏览饭否的最新的timeline,mentions和favorites了,当然,也仅仅只是能浏览而已,所有其他操作都还没做,不过至少证明这个架构是能正常工作的。上张截图吧:
其实是个小功能,真正实现起来还是有点花时间的,那就是移植AutoProxy的功能。在Ninayan中的过程大致如下:
1、从本地读取gfwlist.txt(假如存在的话),然后应用到代理管理器中;
2、从googlecode的svn上下载到最新的gfwlist.txt,然后应用到代理管理器中,如果第一步已经成功执行过了,那么这步的应用到代理管理器的操作会被略过;
3、将下载到的gfwlist.txt替换本地那个老的gfwlist.txt。
应用到代理管理器也不难,首先将gfwlist.txt内容全部读出,然后Base64解码,按行分隔,除掉空行和注释行,剩下有效的规则大约是2700多条。规则分为5类,分别是关键字匹配,主机域名包含匹配,正则表达式匹配,开始字符串匹配以及一种优先级最高的强行不代理规则的匹配。
现在的问题是,代理似乎是能正常工作了,但感觉有点性能问题。于是我就想是不是应该想点其他办法加速这个匹配过程,比较容易想到的是做个简单的缓存,比如已经被匹配过的,需要代理的URL就保存到缓存中,以后有新的代理验证请求来的时候,先在这个缓存中找是不是已经有过,如果有了,就直接返回。这是基于这样一个假设:用户浏览的网站比较集中。而且这个缓存不能大,粗略地想想,可以保持在几十或几百个URL的容量,然后每个URL要维护一个计数,如果缓存一满,就把计数最少的删掉。不过这要注意一个问题,如果时间一长,缓存中的每个记录的计数都很大,然后新的URL就再也进不了缓存了。这种情况很容易出现,比如用户突然从某天开始关注起一个以前都不关注的网站了。其实这个问题也有个笨的简单方案,就是为每个被规则匹配成功的URL都维护一个计数,然后定期选出计数最大的一批URL进缓存。不过这些只是我现在的构想,不知道是否可用,先放着吧,这个问题不是很急。
最后,传张代理配置界面的截图吧,这回是真实数据了。
兵马未动,粮草先行。第一次用Qt,第一次用QML,用QML Viewer做原型,可以强迫自己界面与逻辑分享,大赞啊!于是先把几个主要部分的界面用QML画出来,当然,所有显示的数据都是假的。现在还没想好显示和操作微博的界面应该弄成什么样,本来想模仿FaWave的,可是前些天Reeder把MobileRSS的界面抄袭抖出来后,弄得我不好意思抄别人的了,继续发呆神游天外。先放截图上来,其实用QML的主要原因除了比较容易做出漂亮的界面外,还因为操作上有各种动画效果,这里静态图片上就看不出来了。
另外还有个Paper视图,以paper.li的那种排版显示内容,其实就是一个网页浏览器,现在也没有可看的内容。
腾讯也开放微博API了,这对于一个一贯坚持封闭的公司来说,真是个很艰难的决定。但是,眼下的互联网环境中,开放已经成了大趋势,想想Facebook和Twitter这两种SNS的代表形式,由于API的开放,第三方的应用和客户端真是百花齐放,争奇斗艳,不开放就是死。腾讯在推出微博服务的时候,我猜他们一点都不担心自己的用户数,因为他们自以为有庞大的QQ用户基数支持,只要让QQ客户端支持微博,就能顺利将用户转移过去。事实是国内使用微博的用户,绝大多数不是使用网页端,就是使用手机客户端,同时可以想像得到,目前的QQ死忠用户鉴于他们的年龄,知识构成,社交习惯等因素,很难迅速接受并支持微博这种表达方式,对他们来说,QQ签名就足以支持他们对微博这种媒体形式的需求了,那样更方便,更直观。
开放API,并不是说将微博功能从网页端到其他桌面端或手机端实现一遍就完事了。Twitter在这方面无论是官方还是第三方都有不少的尝试,当然这也跟服务商对微博的定位有关系。比如Twitter之前说过他们做的不是社交服务,而是新闻服务,提供的是内容,所以Twitter官网的上次大改版就是往这个方向上发展的,它更注重内容的展现,希望用户可以方便快捷地获取到各种信息。而国内的诸多微博服务,无一不是停留在最原始的框架下,对于信息的回溯检索,或是扩散都没有任何明显的形式的支持。就像之前ifanr对和菜头的访谈中提到的那样,国内的微博在意识形态上仍然停留在精英制造内容,草根膜拜瞻仰的原始阶段。
这些天推友@lucifierya一直在推一些他对个人知识管理的想法和实践,他主要偏重从网络上获取的信息,包括RSS、Blog、Tweet等。其实这三部分独立的,都有各种实现得很好的方案,两种或三种结合的也有一些方案,但显然就很不被重视了。再回头说腾讯,腾讯有QQ阅读器,有QQ空间,也有微博,三者也有简单的关联,比如QQ阅读器中可以看到好友最新文章,但也仅此而已了。我对@lucifierya的一些想法深以为然,但也许因为他个人缺少对软件开发方面的知识和技能,他提供的解决方案就有点畸形。我在上Twitter的这一年来,一直在考虑自己实现一个Twitter客户端,一开始只是一个单纯的客户端,后来想法就逐渐有所延伸和扩展。单纯的客户端并不是我想要的,我的本意是需要一个获取信息,管理信息的工具。考察和试用了不少其他的服务,想法已经比较完整,但尚未明确和具体,大致如下:
1、连接各微博服务,当然首要是Twitter,提取微博中的网址超链接,作为一个信息源。
2、连接各书签分享服务,比如Delicious,ReadItLater,Instapaper等,作为第二个信息源。
3、订阅RSS以及Google Reader,作为第三个信息源。
4、方便地将超链接分享到微博和书签服务中去。
5、将网页主要内容提取显示。Readability、iReader等扩展的作用很明显,可以极大地提高用户体验,但将这功能放在浏览器中需要用户手工激活,有点繁琐,而在专业的内容阅读器中默认采用这种形式就方便了。
6、将所有内容条目以列表形式组织显示,如Feedly或Reeder那样,可以看到每个条目的开头的一部分信息以及内含图片的缩略图,用户就可以直接判断是否是自己感兴趣的内容。
7、将所有内容条目以报纸排版显示,如QQ阅读器或http://paper.li那样,这样除了有上一条的好处外,更多的是一种贴近传统习惯的用户体验,至少我个人是相当喜欢这种形式,只不过QQ阅读器一页显示的内容太少,以及不能自行添加RSS订阅,而http://paper.li时有乱码,更新周期太长,并且导致有时候一页内空白块太多,不够美观。
8、用户可以对内容添加评论,评论内容和相关链接可以保存到Google Docs上去,这样就可以移动应用了。
以上这些就是我总结出来的大的需求,其他小需求暂且不提。我会自己用Qt慢慢实现,以目前的能力来看,至少可以实现跨Windows/Mac/Linux/Symbian/MeeGo了,也许以后Qt移植到Android和iOS上后,也会支持Android和iOS吧,这是后话了。
在前些天的Nokia World2010中,Twitter的业务开发副总Kevin Thau明确表示,Twitter不是一个社交网络(SNS),而是新闻,是内容,是信息!大言不惭地说,这也是我最近刚刚领悟到的一点。
从半年前,就一直想着自己写一个Twitter客户端,但是不得不说,现在已经有非常多优秀的Twitter客户端了,从共享到免费都有,覆盖了各种平台,那如果我自己要写客户端的话,有什么特色值得用户们抛弃现有的那些客户端来转投这里呢。在这大半年的时间里,我根据自己对SNS的认识,以及自己需求,不断调整心目中的客户端的特性需求,到现在才在心中有一个相对比较固定的框架、模型。
为什么FlipBoard会受到如此热烈的追捧,这就说明对于很大一部分人来说,使用Facebook和Twitter主要并不是为了与人交互和玩游戏,而是为了获取信息,而FlipBoard这种经过整理,同时又有美观排版的方式,很能迎合那些主要为了从网络获取信息的用户的需求。
处于Twitter中文圈中,比较容易忽视的一点是,将Twitter当成一个公共聊天室。当然这也是很大一部分人使用Twitter的目的,传统的网络聊天室的没落,使得用户们不得不将这种需求搬到其他形式的网络服务中,可以看到在各种BBS、论坛、IM群等等都有这种版聊的现象,所以在Twitter中存在这种现象也是正常而且合理的。只不过,从服务提供商的角度讲,应该可以从服务器端,甚至客户端提供这样的信息过滤、隔离的功能,用户可以方便地在两种应用模式间来回切换,想版聊就版聊,想读新闻就读新闻。除了FlipBoard,http://paper.li/也提供了类似的服务,但它目前只能说,这种模式还不错,各种细节方面还很不够。
再扯远一点说,现在很多人应该喜欢使用Google Reader这个服务,但说实话,Google Reader这个界面仍然有很大的改进空间。之前网上一直有人在号召大家使用RSS全文输出,但全文输出后有一个很大的问题是,在Google Reader中如果是全部展开的阅读方式,花费很多时间在拖动滚动条过滤无兴趣的条目上,实际上对于订阅了大量内容的人来说,很多内容只要一眼看到标题,或者其中的某张插图,就没必要看正文了,那现在Google Reader这种阅读方式就显得很落后了。而有一家第三方的Google Reader同步服务在这方面做了不少努力和改进,那就是Feedly。Feedly自己也提供经过分类的新闻内容,但对Google Reader中文用户来说,更有价值的是它的同步Google Reader的功能,可以提取出条目的标题和插图以及正文摘要,并以一定的热度排版,并连接了几家最流行的SNS服务,可以及时分享自己的条目,自从用了Feedly后,我几乎就不用Google Reader的官方界面了(喂喂,你是他们的托儿啊)。
再说回Twitter客户端,目前现在的客户端,基本上都是简单地通过Twitter API将Twitter的Tweet功能从Web搬到桌面或手机端等,几乎没有做更多的需求挖掘。简单地看过几十个完成度较高的Twitter客户端,目前只看到Seesmic Look收集了几组全球知名媒体的账号,但也仅仅是收集,没有更多的特性拓展。现在Twitter推出了新版界面,可以说是诠释了Twitter自己的发展理念,引领了客户端发展的方向──它提供的是新闻,是内容,是信息!
最后可以得出,我想要的客户端,是融合了FlipBoard、http://paper.li/和Feedly几者特色的客户端。它一方面可以向用户提供类似传统书报媒体提供给用户的视觉感观享受,另一方面则是结合网络、计算机的优势,提供大容量、快捷的信息分享功能。所以它不应该只像FlipBoard、http://paper.li/和Feedly它们一样只有一两家内容提供商,它应该是彻底开放的,允许其他内容提供商以固定的接口接入并提供特有的信息。而且它应该有一定的信息自动分类和索引能力,过滤重复或无价值信息,减少用户浪费的时间。
Tag SNS
这几天对Ninayan想了很多。
到目前为止,总的说来,尽管bug还很多,UI还不够精致,操作还不够方便,但功能上已经实现了原来预定的计划中的大部分,除了难度最大的按语义自动按用户喜好定义优先级。
最近轻博客突然吸引了好多眼球,大约两年前其实已经有Tumblr这个产品,只是它并没有大火特火起来。而就最近的几个月里,国内突然冒出好几个同类产品,点点,推他,据说新浪有个Qing。虽然像Twitter、新浪微博这种都有自己的方式展示多媒体信息,但用过轻博客后,明显感觉体验更进一层。于是我就想,其实从客户端层面出发,可以尽量抹平微博客和轻博客的差异,Ninayan就可以往这个方向发展,如果真这么做,无论UI还是底层,都需要做大量修改。
这些天我用新浪微博比较多,同时又不想落下Twitter,同时比较认真地维护两个账号,让我突然意识到,像我这样的人用微博,主要出于两个目的,一是分享自己的状态,二是获取自己关心的信息。而获取信息又可大体分为主动和被动两种,主动是指自己去主动阅读timeline,被动指被别人mention了。于是想到对于同时维护多于1个账号的情况下,提供一种合并显示所有账号的同类信息的功能会很有用,Mixero就有这种将多个账号的timeline显示到一块儿,mentions显示到一块儿等等这种选项,而Ninayan要做的则是可以跨服务合并显示,即比如把Twitter和新浪微博的timeline显示到一块儿。这样做会引发另一个问题是,过滤掉重复信息。这一方向得靠用户自己,仔细甄选该关注的人,比如有的人喜欢用同步工具,结果ta在多个服务中发布的消息几乎是一样的,那么只要在某个服务中关注ta一次就够了;另一方面可以在软件层面识别出相同信息进行过滤。另外要说的是,分享活动,最好是能随时随地方便地进行。这就是说,Ninayan目前光有Windows/Mac/Linux桌面版是不够的,还应该有iOS版和Android版,除了手机版,还要有平板版。还有,最好能自动截取到用户关心的活动,比如能自动获取当前系统中正在播放的歌曲的信息,浏览器正在浏览的网页的标题等等。
暂时就想到这样,好吧,可以做很久很久了。
实在有点不乐意做Deardawn,心理障碍克服不了啊。
Ninayan今天被小言一说,才发现真的是添加不了账号了,原来是之前一次为了加快启动速度的修改,把其他功能破坏掉了,不但添加不上账号,还一开始不能发布消息,只有在显示过home timeline后才可以。
提取了几个model类,这样的实现比较优雅。
几个singleton在程序退出时都正确销毁了。
把AutoProxy的gfwlist信息配置保存到sqlite数据库里了,可以记录每条规则的enable与否,hit次数。在每次程序退出时刷新这些信息到sqlite数据库里。
给几个本地数据库建了几个索引,这样可以让查询速度加快一点点吧。
由于占用内存比较厉害,在Windows下就用::EmptyWorkingSet每分钟清空一次工作集,其他平台不知道有什么类似的方案。但实际上在Windows下如果窗口最小化时,内存会被一下子回收好多,不知道到底是怎么回事的。
本地数据库读写冲突的问题还没想到比较低成本的解决方案,叹气。
停下来想想,现在已经实现的功能也只是玩玩而已,最有用的应该还是Google Reader支持吧,可惜没找到确认无误的API文档。
blog被墙了就真不太想更新了。
Ninayan这段时间除了不时地发现些bug,然后修正外,主要是增加了对163、Sina、Sohu、QQ微博的支持。从开发者角度讲,163的API是最接近Twitter了,QQ的API设计最山寨,完全自己搞了一套,Sina和Sohu从技术角度讲跟QQ接近,接口设计仍然是模仿Twitter。
然后在google code上放了Linux版的可执行文件上去,今天才知道原来各发行版上普通的应用程序是可以做到二进制兼容的,也怪我以前看CodeLite、Code::Blocks它们都为每个发行版提供一个独立的安装包,就先入为主地以为每个发行版都要各自单独编译才行。今天突然想到Qt Creator就是同一个可执行文件在所有Linux发行版里可以运行,只是区分了32位和64位而已。我还傻乎乎地在12个系统里都编译了一把Qt,再分别编译出Ninayan,再分别打包,再分别上传,天呐!
首先一件很郁闷的事,貌似域名被墙了,直接用IP是可以打开本blog的,但是我暂时又不想去折腾这些了,先这么放着吧,问候下方校长18代祖宗及全体女性家属。
Ninayan最近动作倒是不大了,主要是先打了Mac,Win32和Linux的安装包给几个人试用了一下,结果反响很差,有点失落,难道真的定位有问题?
不过说起来,Ninayan现在也只是个雏形,真正的主要的理念需要的特性并没有实现,现在也只是把图片,视频和文章链接单独提取出来可以独立浏览而已,并没有做进一步的工作,比如要能打tag,可以检索,自动语义过滤,优先级排序等等。其次是RSS聚合也没做,Google Reader没实现,UI缺少专业的美工设计等等,总之可以做的工作还有很多很多。
另外,今天勉强让Ninayan在我的Nokia 5230上运行起来了,解决了不少问题,但最终还是由于报内存不足而自动退出。为了让Ninayan可以在5230上运行,遇到了不少问题。首先是开发环境的建立,我用的是Qt SDK 1.1 beta,这个SDK用的是Qt 4.7.2,但有bug,for S60v5的配置文件使用了for Symbian^3的配置,所以编译工程的时候会出错,要自己在工程的.pro里把opengl的配置去掉。其次是部署时,要安装Qt,还要单独安装sqlite,据说以前版本是合在一个安装包里的。最后是这两天一直在纠结的问题,运行后在TextInput获取输入焦点后,虚拟键盘没有显示出来,在Nokia的论坛和Stackoverflow上问,都没人回复,今天偶然想起qDou,试了下它在5230上至少是可以输入文字的,虽然之后会崩溃,于是发邮件问了一下作者,作者给了个网址,原来是我在TextInput控件一起放了个兄弟控件MouseArea,于是TextInput没能收到点击事件,于是虚拟键盘不会自动显示,只要自己强制调用它的openSoftwareInputPanel方法就可以了。
至于最后的自动退出,从现象结合网上的人们的讨论来看,似乎是因为同时请求的网络连接太多,以及内存占用过多引起的。叹气,桌面程序写惯了,散漫惯了,都不怎么注意内存的使用了,反而经常采取以空间换时间的策略,看来如果真要让Ninayan能在手机上正常跑起来的话,还得好好重新设计一下,把各种请求都放进队列里,不要一下并发几十个连接,其他的内存使用策略也得仔细看看,有点想看看侯捷翻译的那本讲内存受限系统的程序开发的书了。
Ninayan的主要功能基本上都做出来了,剩下的主要是增加各种服务的支持,比如各种微博,各种SNS,以及Google Reader。其次便是界面和操作上的细节方面的调整,现在还是很粗糙的。
离上次W.I.P.已经有3周多了,这3周主要实现了文章浏览特性。文章浏览有3种模式,一种是仿feedly的可扩展的列表,一种是信reeder的分栏,还有一种是仿paper.li的报纸模式。但是,目前的效果还远远没达到预期。放几张图吧:
还增加了个视频观看视图,这是计划外的,但觉得有必要,也很粗糙:
直到这里才发现,在Mac OS X 10.6.6上一直以64位Cocoa编译的Qt,果然视频播放不了了,不记得在哪里看到过说明,QtWebKit在Mac上如果是64位的话是载入不了Flash播放插件的,因为Flash播放器稳定发布只有32位版本,于是在Mac上也自己编译了一把Qt,改成32位Cocoa框架的就可以了播放视频了,太纠结了,也难怪乔帮主要封杀Flash了。
今天觉得Ninayan大部分功能已经实现了,也差不多快可以发布beta版了,于是要打包,先解决Windows和Mac上的打包问题。 Windows上一直以来我都习惯用Inno Setup了,所以在如何制作安装包的问题上并不纠结,InnoIDE和ISTool都是很方便的工具,主要的问题在于解决Qt的插件的部署。Ninayan在Windows上也是用GCC(MinGW)编译的,相比VS2008,少了个SxS的问题,只要带两个dll一起发布就行了。Qt本身有一种简单但比较有用的插件机制,它的字符编码支持CJK,图形文件格式支持,数据库驱动等等都是由插件实现的。也就是说$(QTDIR)/plugins下的东西都要跟着发布,而且程序代码中需要自己在main()中,app对象创建后及时调用QCoreApplication::addLibraryPath()添加plugins的路径。另外由于用到了QtWebKit和QML,QDeclarativeEngine对象也需要指定一下qmlwebkitplugin插件的目录,把$(QTDIR)/imports/QtWebKit目录打包进去,然后在代码中调用QDeclarativeEngine::addImportPath()添加路径,这样整个目录就是发布的所有内容了。 在Mac OSX上比较流行用dmg,但这之前还要解决Qt的framework链接的问题。Qt在Mac OSX下官方发布的二进制包是framework形式的,这跟Windows下有点不同,呃,其实跟SxS有点类似。要用install_name_tool -change命令行修改自己的程序可执行文件链接的framework的位置,这个工作可以由Qt自带的一个叫macdeployqt的小工具完成,只要在命令行执行macdeployqt Ninayan.app就可以了。不过除此之外,还是由于qmlwebkitplugin的缘故,需要自己复制这个插件到程序的bundle中,我就放在跟最终的可执行文件相同的目录中,这个插件macdeployqt并不处理,除了要自己复制,还要自己用install_name_tool来修改链接的framework。这样操作后,是一个可以正常运行的,完整的应用程序bundle,整个bundle就有113MB,谁让Qt那么大呢!然后是把这个bundle打包成dmg。Mac OSX自带免费的工具,GUI和CUI的都有,GUI的叫Disk Utility,不过看了下感觉界面挺复杂的,还是用命令行的hdiutil爽,而且我前面是用命令行修改的符号链接,这里当然最好也是用命令行打包,这样一个shell脚本就能搞定编译后生成dmg的所有事情了。用hdiutil的话,这个命令行就可以打出一个dmg来: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDZO -ov Ninayan.dmg 不过这个有点土,就是把Ninayan.app放成了dmg而已,其他什么都没有。我的要求其实也很简单,有自定义的背景图片,有Applications目录的链接,这样用户打开这个dmg就可以完成把Ninayan拖拽到Applications目录中的操作。在网上找了不少文章和视频,多是用其他的GUI工具,在stackoverflow上有个家伙用AppleScript写了段脚本,确实通用性和灵活性都比较好了。最后我选了条简易简陋没通用性的路子,但够用。首先需要明白的是,dmg被Finder打开后,就是当成一个普通的文件夹处理的,所以它的背景什么的设置,都是放在.DS_Store文件中的(Mac中以dot开头的文件都会自动隐藏),所以很dirty的做法是,先用这个命令行创建一个可读可写的dmg并挂载: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDRW -size...
已经不记得有几个大年三十的晚上是在电脑前写代码度过了,今年破天荒的因为客厅里电视在放春晚,打偶然走过去看几眼。
今天把超链接处理模块重构了,之前那个实现在Mac下崩溃得比较频繁,但在Windows和Linux下却不是很多。对于这个现象我有点疑惑,虽然说代码确实是写得有问题,但为什么只有在Mac才比较明显呢。好在Mac下崩溃了打印出来的栈回调信息比较详细,几乎能跟踪到最终引起崩溃的代码行。
原来的实现把所有中间数据结构以指针的形式保存在一个list里,然后在自认为结束的时候销毁对象。这样的做法本没有什么问题,关键是我在操作这个list时并没有考虑重入的情况。于是重构主要做了两个重大修改,一是在list中直接保存对象,而不是指针,这样更不容易写错;二是对list操作大部分情况下都加mutex锁住。顺便也修正了些其他的小问题,比如原来即使是基于embed.ly的服务识别url是图片还是视频也有问题,其实embed.ly是返回了这个类型的。
另外,今天还把主界面针对360*640分辨率修改了一下,因为Nokia的S60v5和Symbian^3现在几个机型都是用这个分辨率的。至此,图片浏览特性的实现暂时告一段落,接下来该实现文章阅读了。昨天大致研究了一下Readability,发现它在Firefox表现那么风骚,结果在QtWebkit下总是返回不能分析的错误。不知道是DOM树的实现还是JavaScript引擎的问题。难道真要我移植一个C++版本,这实在太费时费力,还不好维护了。
最后,上个最新界面截图。
终于勉强加上了一个功能比较凑合的图片浏览功能,还有很多地方需要改善。本来我的想法是UI上直接拿QML Demo PhotoViewer的代码来用的,可是昨天发现PhotoViewer中的代码会导致在Windows下程序不能切换输入法,于是只好自己写了。自己写就极大地简化了功能,才简化了代码,于是最后所有东西都放在一个QML文件中写完了,最终的效果,也就是几个视图场景切换时那个动画效果没有了。残念!
另外有个问题是图片下载的问题,现在的Twitter上比较流行的图床大多是被墙的,如果让QML的引擎自己通过代理下载图片,感觉不是一般的慢!所以我就觉得把这些图片事先下载到本地缓存起来似乎挺有必要的。
还有个比较重要的问题是全屏模式下浏览图片,默认是自动拉伸到整个显示区了,这样似乎比较影响显示性能,当然也是机器配置不是那么好的才会有这种卡的情况,在我的T43上会卡,拿到Mac mini上就流畅了。应该稍微改一下,看一下是不是在加载前就获取图片本身的尺寸,如果比显示区域大,才缩放,不大的话,就以图片本身的大小显示了,这样显示也更清晰点。
还有个浏览某张图片的大图就不截了,没啥好看的。
有些问题,总是那么奇怪。因为XP里的虚拟机在跑Debian编译Qt,于是在Mac下把QML的Demo PhotoView抠过来用,本来就很吃力,还顺带发现了一个因为先后顺序问题引起的崩溃bug,终于可以在Ninayan里看到PhotoView的样子了。可是到了晚上突然发现,在Windows下不能切换输入法了,一切换Ninayan就挂死!经过一部分一部分地屏蔽代码发现,引起这个问题的似乎是VirtualDataModel中Package的一些代码。好吧,决定索性不用抠别人的代码,用自己的方法写一遍相同的UI吧。
上一段提到,我又蛋疼地在Debian里编译Qt了,嗯,又花了一下午。之后就是编译Ninayan,呃,我现在最大的乐趣就在于在不同的系统里编译Ninayan并用它来上Twitter了,囧rz。想来也不会有多大问题,毕竟之前在Arch和Mint里都比较顺利的,唯一大的区别是在Arch和Mint里桌面都是用Gnome,而这次Debian里用的是KDE,很花哨的感觉。言归正传,Ninayan运行得很顺利,除了字体不太好看。在Twitter上报怨了一下后,@truthurt建议自带一个开源的字体,真是个不错的主意,在Mint里的那种就很好,我后来去网上找了文泉驿的微米黑,在Debian和Arch里效果都很好。其实昨天就想过字体的问题,不过当时想到的是直接将字体装入到系统中,然后在程序中直接通过字体family名使用。今天偶然想到,其实可以程序直接载入指定路径的字体文件来使用的!不过Windows下还是用微软雅黑吧,微米黑在XP下同一个字的不同笔画都有粗细差异,真糟糕。
今天照计划,实现了查看对话的功能,不过不完善,因为网络传输的原因,是一条消息一条消息从服务器获取后显示,如果显示到一半切断,又要显示另一组对话,就会把前一组对话后面没显示的那些消息作为后一组对话的消息。所以要考虑一下怎么加一个中断的机制,不过这个留到以后版本中完善吧,毕竟Ninayan一开始定位就不是一个完善的客户端。
然后又蛋疼地去装ArchLinux了。这个发行版安装比Ubuntu麻烦多了,它的iso镜像只装一个最基本的字符界面,然后带一个pacman包管理工具,GNOME之类的桌面需要自己再另外安装,所以最好有比较畅通的网络。
装完后,中文字体的显示惨不忍睹,google随便搜了一下,也挺折腾的,我懒得弄了。我就是想在上面试试编译Ninayan。没想到可以用pacman安装已经编译好的Qt 4.7.1,再装个Qt Creator,就可以编译Ninayan了。除了显示的字体不好外,其他的还算凑合吧。
明天开始做图片浏览和文章阅读功能吧。
昨天和前天晚上蛋疼地在Linux上编译Ninayan了。我用的是Mint9,也就是一个Ubuntu的修改版。在Linux上编译Qt程序有点麻烦的是需要自己编译一遍Qt,前天晚上就编译了一遍最新的qt-everywhere-opensource-src-4.7.1.tar.gz,过程比较顺利,再装上Qt Creator就可以编译出Ninayan了,简单试用了一下,很正常。而且令我比较惊讶的是,我学Hotot用了Droid Sans字体,最终的显示效果在我个人看来比Windows XP SP3和Mac OS 10.6.6上都要好,但XP SP3上加上Gdipp或MacType后,效果会有很大的提升。
昨天突然发现,Ninayan在Mint下不能访问https://api.twitter.com(不是被墙的缘故),测试了几次才确认是不能访问https的地址,于是想到前不久看过一篇博文说Qt 4.7是有这么个bug不能访问https的,因为原来Qt 4.6带了SSL证书,而Qt 4.7没带,于是照那篇文章的作者的说法,从Qt 4.6.2里找到qt-ca-bundle.crt文件,然后每次QNetworkRequest在被post或get前都设置一下Ssl证书。结果我的情况是连编译都不通过,于是可以确认是Qt在编译时没有编译进OpenSSL了。然后找到了这篇《Compile Qt 4.7 on Ubuntu 10.10》,先要安装一堆的库的开发包,再来编译Qt,最后再编译Ninayan,果然就正常了!于是我就不明白那篇博文讲述的到底是个神马问题了!
今天就比较烦躁地在做网址缩短功能了。本来打算内置goo.gl,bit.ly和is.gd三个短网址服务,结果很郁闷的是bit.ly总是返回INVALID_URI,但同样的URL我拿到Firefox下测试就能返回正确的数据,这不是歧视嘛,难道是在http header里还要设置神马东西?倒是goo.gl和is.gd都正常了!
话说前天偶然发现了MacType和Gdipp,觉得这种功能对Ninayan之类偏阅读的应用非常有帮助,于是我在极限论坛上给MacType的作者私下发了个email询问是否可以提供专门的API以便集成此功能。不过到现在也没收到回应,估计是不愿意了。
今天看了一下MacType的安装目录,发现有个MacLoader.exe,而Gdipp的安装目录下也有个loader文件,这时才明白过来,可以通过把可执行文件的完整路径作为命令行参数传递给这loader,那么该可执行文件会被启动运行,并被注入实现字体渲染增强效果。
经过简单的测试,Ninayan在我的XP SP3上使用微软雅黑字体,加上增强字体渲染效果,感觉确实更舒服了!而Gdipp是以GPLv3,最新的版本好像是用LGPL了,一起打包发布应该是木有问题的。我只要另外再写一个小小的启动程序,在安装包中把启动程序作为快捷方式添加到开始菜单和桌面等位置,可以自己调整是否使用增强字体渲染效果,使用什么样的渲染配置等等。
这样一来,似乎Windows上的效果都超过Mac上的了,一直没找到感觉特别好的Mac上的用于大段文字阅读的字体,微软雅黑只适合在Windows上用,而且至少要开了ClearType Tuner才行,有MacType或Gdipp最好。也许是因为我在Mac下用的是CRT的显示器的缘故,不止一个人对我说过那个视频信号转换后损失挺大的,也许用LCD的就要好些了!
今天心情不错,呼呼!
前面说到内存泄漏的问题。后来通过逐段屏蔽代码,终于找到了最大一处泄漏源。这个办法比较笨,但这次真的有用,主要还是因为程序结构简单,流程也不复杂才能用吧。
程序大体上分为三部分,UI层,数据层,网络通信层。用户在UI层上操作,1、UI层向数据层请求数据,2、数据层根据不同情况直接查询本地数据库或通过网络通信层获取数据,3、网络通信层自己有一个定时轮循的任务,每分钟从远程服务器获取数据,4、有了数据就发送给数据层,5、数据层将数据经过简单处理发送给UI层,6、然后显示,就是这么简单。
我开始主要怀疑UI显示调用的Qt/QML也许MM有问题,于是把最终UI显示的代码屏蔽掉。发现仍然泄漏的情况基本没有变化,说明跟UI显示的关系不大。后来发现Mem Usage的增长是有周期,大概是1分钟1次,那么可以确定是在4和5两步有问题。这时把第5步中代码全部屏蔽掉,果然Mem Usage就不增长了。然后逐步缩小范围,一点点放出代码,最后发现竟然是QSqlQuery查询本地数据库时,select出来的东西需要程序员自己clear掉!内牛满面啊,果然是Qt用得有问题!
今天偶然发现一个叫MacType的东东,可以在Windows下以进程注入的方式给指定进程增强字体渲染效果。跟微软官方的ClearType Tuner是一类东西,不过MacType的选项更丰富。于是我想到,我这个以阅读为主的工具,要是集成这么个美仑美奂的功能,该是多酷啊。在极限论坛翻了一遍帖子,貌似MacType是闭源的,另外有个新生的Gdipp项目,倒是在googlecode上开源了,不过听说它的配置复杂,而且目前不够稳定,尤其是32位系统上。好吧,反正这种功能对我有致命吸引力,一定要集成!
内存泄漏的问题,调得我心力交瘁,都有点神经衰弱了,甚至有点绝望,唉。以前还真没有过这种强烈的负面情绪出现过。
每次UI刷新,从任务管理器里看Mem Usage都会增加2-3MB,这得有多严重的泄漏啊!可是我自己的代码中new出来的对象都经过跟踪是销毁掉了的。于是又把矛头指向Qt内部,或者是QML中了。
本来怀疑是QML中的实现可能有问题,于是把Qt从4.7.0升级到4.7.1,貌似泄漏得更严重了。所以现在都已经不敢怀疑是Qt有问题了,开始怀疑是没有遵循Qt的用法。有些Qt返回的东西,需要程序员来负责销毁,比如QNetworkAccessManager在调用get或post后返回的QNetworkReply对象,这是多么操蛋的设计啊,指不定就是每次在哪里它自己创建出一堆对象出来要我来销毁我却不知道呢!
从CodeProject上下载了个Visual Leaks Detector,从说明上看,说是在msvc的jit debugger里会自动打印信息到debugging output window里的,可我实际上试了之后,发现屁都没输出一句,难道它是for MFC-based project only的?有可能的,唉!
简直走投无路了。
本来排除在计划外的事情,今天又去搞了,就是支持Twip4。前一天也折腾过一下,没弄好,这回问了一下Twip4的作者@yegle,他开始说是计算数字签名时用https://api.twitter.com/作为base string就行了。我试了下不行,后来他又说试试T模式吧,有几个客户端是经过实践T模式没问题的。于是一下子就明白过来了。 Twip4有T模式和O模式两种工作模式。T模式是完全的透明转发,Twip基本上不做任何处理,所以要请求oauth token和oauth token secret时原本是向https://api.twitter.com/oauth/access_token请求的,同时也是拿https://api.twitter.com/oauth/access_token作为base string计算数字签名的,在使用T模式的代理时,只要向http://www.myproxy.com/oauth/access_token请求就行了,仍然用https://api.twitter.com/oauth/access_token作为base string计算数字签名,这样就能无障碍获取oauth token和oauth token secret了。至于O模式,我看了下TweetDeck和Mixero的表现,发现它们也并不向O模式Twip请求oauth token和oauth token secret,或者请求了也没结果。所以我就推测其实O模式是没这功能的,O模式自己有consumer key和consumer secret,所以自己有一套oauth token和oauth token secret,但不是给客户端用的,即使客户端用自己有效的oauth token和oauth token secret发送给Twip请求,Twip也会把http header和url parameters里的东西处理一遍,用自己的那套oauth token和oauth token secret计算出来的东西替换掉。所以我想如果用O模式也要让用户可以无障碍认证的话,需要软件自己提供一个透明代理,软件先拿用户名和密码从那透明代理处获取oauth token和oauth token secret,然后在其他发布消息,收取消息时用O模式代理,就可以解决这个问题了。...
好吧,其实没做什么,本来的计划是先做图片浏览和文章阅读的,可是饭否上的内容实在太单薄了点,呃,这纯粹是借口,于是今天实现了对Twitter的支持。
昨天晚上弄到1点半才基本搞好怎么用xAuth认证获取oauth token和oauth token secret,今天就把twitter的timeline浏览,direct message浏览以及消息发布实现了。这内容比饭否丰富了许多,比如有了3列跟retweet有关的内容。twitter居然没有像饭否那样可以一次请求把foing和foer列表取下来,而只能先获取那些id,再由id去获取其他信息!于是这个功能就还没实现。还有比较影响使用的没实现的功能包括不能看conversation,不支持list,不能用快捷键操作。
不过有点值得欣慰的是,又修正了几处内存泄漏的问题。
今天就不上图了,因为基本上界面上没啥变化。
脑袋混沌了一天,终于基本上搞定超链接处理的功能了。
最开始是由于我使用的处理流程的关系,选择一个合适的数据结构让我头疼了好久,最后决定使用一个list,每个元素是一个结构体,每个结构体由两部分组织,一部分是URL列表,该列表会按短网址还原后的处理顺序存储URL,另一部分则是对该URL的描述,描述的字段包括当前是否已经完成全部的还原操作,最后一个URL能不能被embed.ly拆成两个新的URL列表,代表视频的html和html5等信息。
中间调试过程也是经历了重重磨难啊!其实也是自己代码写得有问题。一开始我是用一个map来存储url list和附着属性的,指针乱飘,调试得没有信心了,才改成上面描述的那个方案。还是有很多问题,经过层层排查,终于把所有的问题都找出来并解决掉了。甚至以为Qt的signal不能随便emit,会有对象生命周期相关的问题,最后也确认其实是在前面的代码写得有问题,哇哈哈!
明天就看一下怎么把数据库中的已有记录读取出来当历史记录来处理超链接。然后就可以做图片浏览的功能了!图片浏览功能完成后就做Readability的功能,之后再做twitter的支持,这就可以发布第一个版本了!
根据@zhangh109的建议,修改了一下界面,浏览文章有三种模式,在启动界面现在就只有一个入口Article View,在Article View中再添加切换浏览模式的入口。另外了加个图片浏览的视图,在启动界面中把原来About的入口替换掉了,About则移到原来的Quit按钮处。
URL处理部分今天还是没有搞定,不过思路清晰了很多,估计明天就可以完成总体的框架,到时候图片浏览部分应该就可以很快实现,而文章浏览部分需要把Readability的JavaScript代码移植过来,本来如果可以直接用它的那些JavaScript代码是最好的方案,可是之前我曾尝试过,不知道为什么内嵌的Webkit在装载完页面后,直接运行那个代码是没有作用的。所以干脆也不研究它了,直接移植成C++的,用Qt的接口操作Webkit的DOM树来解决吧。想来这移植工作需要花一些时间吧。
贴两张修改后的截图吧。
今天在处理超链接的问题,这是最重要的一环。
Ninayan提供给用户的信息分两大类:图片/视频和文章,微博消息只算是附属品。所以从微博消息中得到一个URL后,最终要能正确识别出它是一个图片/视频,还是一篇文章(当然,文章中也可以有图片和视频,但重点是它有文字),对于其他不可识别的类型,比如zip,则忽略。
我设计了如下的处理流程:
1、将URL与embed.ly可处理的类型用正则表达式匹配一下,如果可以匹配上,则用embed.ly处理,不能匹配上,则假设它是个短网址,将其还原成长网址。
2、embed.ly处理后,会返回缩略图和原图(如果是视频,则是一段HTML,可能还会有一段HTML5代码)的URL,假设这URL也是个短网址,也将其还原成长网址。
3、还原成长网址后,与原来的短网址比较,如果两者不相等,则假设该长网址仍然是个短网址,继续还原,如此循环迭代,直到还原失败或两者相等,最后还原的最终长网址与embed.ly可处理的类型用正则表达式匹配一下,如果可以匹配上,则用embed.ly处理。
4、如果第3步最终的长网址不能与embed.ly匹配上,则认为该网址是真正的最终应该由Ninayan处理的网址,可分为前面说的两类,图片/视频和文章。
至于怎么辨别出属于哪一类,我决定采用一个很粗糙的办法,如果前面经过embed.ly处理过的,那么肯定是图片/视频,或者URL最后是以诸如.jpg/.png/.gif等known的图片/视频文件扩展名结尾,那么也是图片/视频,其他的则都划入文章类型。而文章类型其实是个很粗糙的结果,网页是要经过像Readability那样的处理才是最终显示给用户的,而在Readability处理的过程中,可以过滤掉诸如.zip等不支持的文件类型的。
这个方案也只是考虑到了URL在网络交互上的处理过程。还有这处理结果怎么通知本地数据存储模块和UI显示模块,也是个问题。而这个问题涉及到何时通知,通知时采用什么数据结构,以及本地存储时采用什么数据结构。
添加了个图片本地缓存的功能,结果发现不是很好用。在Windows下实际使用时发现有时候装载本地文件仍然很慢,甚至不如直接从网络上加载的快。在Mac下发现压根就装载不上。初步估计是因为多处同时读写文件时有冲突,需要再仔细看看。
把删除消息,去fav后的响应也添加上了。
另外还有些细节方便的调整,比如所有显示图片的地方都添加了等待动画。
最后发现个奇怪的问题,在Mac下读取Friends列表有问题,json解析失败,这太诡异了。
今天听@shellexy说,用HTML5的话,配合JS/CSS这些东东,可以实现跨iOS/Android/WebOS/Symbian/MeeGo,呃,这也太强大了吧,而且据说Hotot移植到这些平台已经是在计划中了。得好好考察一番这种开发方案了。
昨天突然发现有内存泄漏,确实找到几次没有释放的,后来从任务管理器里看,貌似还有泄漏,但实在找不出有什么地方有问题了,最后今天把所有自己new和delete都放在一个类中统一调度跟踪,发现确实是都正确释放了的,只好先不管了。
今天搞定了显示friends和followers列表的功能,增加了显示所有自己发布的消息的功能。明天就搞一下显示之前的消息的功能。之后再修改一下消息显示的格式,比如图片预览,超链接处理等,然后就算是完成一个milestone了吧。
不多说,也是上两张图,还被@shellexy嘲笑了说~
经过一天的折腾,Ninayan已经能完成跟消息相关的绝大多数操作了,私信也搞定了。作为一个纯粹的微博客户端来说,也就剩下图片上传和用户Profile查看没做了。更多的诸如图片预览等功能属于比较有用的增值功能,不在这个范畴内。
汇报一下进度,Fanfou的API果然是最简单的,现在除了可以浏览时间线,回复线和收藏外,已经可以做些基本的操作了,比如发消息,当然包括回复,收藏和取消收藏,删除消息。而且也把消息都保存到本地了,每次切换页面时,显示消息的速度就相比以前会快一点,以前是每次都要从服务器上取下来才能显示。
接下来要解决的是,发布消息后刷新界面,以及消息中的超链接处理等细节问题。
今天折腾下来后,已经可以浏览饭否的最新的timeline,mentions和favorites了,当然,也仅仅只是能浏览而已,所有其他操作都还没做,不过至少证明这个架构是能正常工作的。上张截图吧:
其实是个小功能,真正实现起来还是有点花时间的,那就是移植AutoProxy的功能。在Ninayan中的过程大致如下:
1、从本地读取gfwlist.txt(假如存在的话),然后应用到代理管理器中;
2、从googlecode的svn上下载到最新的gfwlist.txt,然后应用到代理管理器中,如果第一步已经成功执行过了,那么这步的应用到代理管理器的操作会被略过;
3、将下载到的gfwlist.txt替换本地那个老的gfwlist.txt。
应用到代理管理器也不难,首先将gfwlist.txt内容全部读出,然后Base64解码,按行分隔,除掉空行和注释行,剩下有效的规则大约是2700多条。规则分为5类,分别是关键字匹配,主机域名包含匹配,正则表达式匹配,开始字符串匹配以及一种优先级最高的强行不代理规则的匹配。
现在的问题是,代理似乎是能正常工作了,但感觉有点性能问题。于是我就想是不是应该想点其他办法加速这个匹配过程,比较容易想到的是做个简单的缓存,比如已经被匹配过的,需要代理的URL就保存到缓存中,以后有新的代理验证请求来的时候,先在这个缓存中找是不是已经有过,如果有了,就直接返回。这是基于这样一个假设:用户浏览的网站比较集中。而且这个缓存不能大,粗略地想想,可以保持在几十或几百个URL的容量,然后每个URL要维护一个计数,如果缓存一满,就把计数最少的删掉。不过这要注意一个问题,如果时间一长,缓存中的每个记录的计数都很大,然后新的URL就再也进不了缓存了。这种情况很容易出现,比如用户突然从某天开始关注起一个以前都不关注的网站了。其实这个问题也有个笨的简单方案,就是为每个被规则匹配成功的URL都维护一个计数,然后定期选出计数最大的一批URL进缓存。不过这些只是我现在的构想,不知道是否可用,先放着吧,这个问题不是很急。
最后,传张代理配置界面的截图吧,这回是真实数据了。
兵马未动,粮草先行。第一次用Qt,第一次用QML,用QML Viewer做原型,可以强迫自己界面与逻辑分享,大赞啊!于是先把几个主要部分的界面用QML画出来,当然,所有显示的数据都是假的。现在还没想好显示和操作微博的界面应该弄成什么样,本来想模仿FaWave的,可是前些天Reeder把MobileRSS的界面抄袭抖出来后,弄得我不好意思抄别人的了,继续发呆神游天外。先放截图上来,其实用QML的主要原因除了比较容易做出漂亮的界面外,还因为操作上有各种动画效果,这里静态图片上就看不出来了。
另外还有个Paper视图,以paper.li的那种排版显示内容,其实就是一个网页浏览器,现在也没有可看的内容。
腾讯也开放微博API了,这对于一个一贯坚持封闭的公司来说,真是个很艰难的决定。但是,眼下的互联网环境中,开放已经成了大趋势,想想Facebook和Twitter这两种SNS的代表形式,由于API的开放,第三方的应用和客户端真是百花齐放,争奇斗艳,不开放就是死。腾讯在推出微博服务的时候,我猜他们一点都不担心自己的用户数,因为他们自以为有庞大的QQ用户基数支持,只要让QQ客户端支持微博,就能顺利将用户转移过去。事实是国内使用微博的用户,绝大多数不是使用网页端,就是使用手机客户端,同时可以想像得到,目前的QQ死忠用户鉴于他们的年龄,知识构成,社交习惯等因素,很难迅速接受并支持微博这种表达方式,对他们来说,QQ签名就足以支持他们对微博这种媒体形式的需求了,那样更方便,更直观。
开放API,并不是说将微博功能从网页端到其他桌面端或手机端实现一遍就完事了。Twitter在这方面无论是官方还是第三方都有不少的尝试,当然这也跟服务商对微博的定位有关系。比如Twitter之前说过他们做的不是社交服务,而是新闻服务,提供的是内容,所以Twitter官网的上次大改版就是往这个方向上发展的,它更注重内容的展现,希望用户可以方便快捷地获取到各种信息。而国内的诸多微博服务,无一不是停留在最原始的框架下,对于信息的回溯检索,或是扩散都没有任何明显的形式的支持。就像之前ifanr对和菜头的访谈中提到的那样,国内的微博在意识形态上仍然停留在精英制造内容,草根膜拜瞻仰的原始阶段。
这些天推友@lucifierya一直在推一些他对个人知识管理的想法和实践,他主要偏重从网络上获取的信息,包括RSS、Blog、Tweet等。其实这三部分独立的,都有各种实现得很好的方案,两种或三种结合的也有一些方案,但显然就很不被重视了。再回头说腾讯,腾讯有QQ阅读器,有QQ空间,也有微博,三者也有简单的关联,比如QQ阅读器中可以看到好友最新文章,但也仅此而已了。我对@lucifierya的一些想法深以为然,但也许因为他个人缺少对软件开发方面的知识和技能,他提供的解决方案就有点畸形。我在上Twitter的这一年来,一直在考虑自己实现一个Twitter客户端,一开始只是一个单纯的客户端,后来想法就逐渐有所延伸和扩展。单纯的客户端并不是我想要的,我的本意是需要一个获取信息,管理信息的工具。考察和试用了不少其他的服务,想法已经比较完整,但尚未明确和具体,大致如下:
1、连接各微博服务,当然首要是Twitter,提取微博中的网址超链接,作为一个信息源。
2、连接各书签分享服务,比如Delicious,ReadItLater,Instapaper等,作为第二个信息源。
3、订阅RSS以及Google Reader,作为第三个信息源。
4、方便地将超链接分享到微博和书签服务中去。
5、将网页主要内容提取显示。Readability、iReader等扩展的作用很明显,可以极大地提高用户体验,但将这功能放在浏览器中需要用户手工激活,有点繁琐,而在专业的内容阅读器中默认采用这种形式就方便了。
6、将所有内容条目以列表形式组织显示,如Feedly或Reeder那样,可以看到每个条目的开头的一部分信息以及内含图片的缩略图,用户就可以直接判断是否是自己感兴趣的内容。
7、将所有内容条目以报纸排版显示,如QQ阅读器或http://paper.li那样,这样除了有上一条的好处外,更多的是一种贴近传统习惯的用户体验,至少我个人是相当喜欢这种形式,只不过QQ阅读器一页显示的内容太少,以及不能自行添加RSS订阅,而http://paper.li时有乱码,更新周期太长,并且导致有时候一页内空白块太多,不够美观。
8、用户可以对内容添加评论,评论内容和相关链接可以保存到Google Docs上去,这样就可以移动应用了。
以上这些就是我总结出来的大的需求,其他小需求暂且不提。我会自己用Qt慢慢实现,以目前的能力来看,至少可以实现跨Windows/Mac/Linux/Symbian/MeeGo了,也许以后Qt移植到Android和iOS上后,也会支持Android和iOS吧,这是后话了。
在前些天的Nokia World2010中,Twitter的业务开发副总Kevin Thau明确表示,Twitter不是一个社交网络(SNS),而是新闻,是内容,是信息!大言不惭地说,这也是我最近刚刚领悟到的一点。
从半年前,就一直想着自己写一个Twitter客户端,但是不得不说,现在已经有非常多优秀的Twitter客户端了,从共享到免费都有,覆盖了各种平台,那如果我自己要写客户端的话,有什么特色值得用户们抛弃现有的那些客户端来转投这里呢。在这大半年的时间里,我根据自己对SNS的认识,以及自己需求,不断调整心目中的客户端的特性需求,到现在才在心中有一个相对比较固定的框架、模型。
为什么FlipBoard会受到如此热烈的追捧,这就说明对于很大一部分人来说,使用Facebook和Twitter主要并不是为了与人交互和玩游戏,而是为了获取信息,而FlipBoard这种经过整理,同时又有美观排版的方式,很能迎合那些主要为了从网络获取信息的用户的需求。
处于Twitter中文圈中,比较容易忽视的一点是,将Twitter当成一个公共聊天室。当然这也是很大一部分人使用Twitter的目的,传统的网络聊天室的没落,使得用户们不得不将这种需求搬到其他形式的网络服务中,可以看到在各种BBS、论坛、IM群等等都有这种版聊的现象,所以在Twitter中存在这种现象也是正常而且合理的。只不过,从服务提供商的角度讲,应该可以从服务器端,甚至客户端提供这样的信息过滤、隔离的功能,用户可以方便地在两种应用模式间来回切换,想版聊就版聊,想读新闻就读新闻。除了FlipBoard,http://paper.li/也提供了类似的服务,但它目前只能说,这种模式还不错,各种细节方面还很不够。
再扯远一点说,现在很多人应该喜欢使用Google Reader这个服务,但说实话,Google Reader这个界面仍然有很大的改进空间。之前网上一直有人在号召大家使用RSS全文输出,但全文输出后有一个很大的问题是,在Google Reader中如果是全部展开的阅读方式,花费很多时间在拖动滚动条过滤无兴趣的条目上,实际上对于订阅了大量内容的人来说,很多内容只要一眼看到标题,或者其中的某张插图,就没必要看正文了,那现在Google Reader这种阅读方式就显得很落后了。而有一家第三方的Google Reader同步服务在这方面做了不少努力和改进,那就是Feedly。Feedly自己也提供经过分类的新闻内容,但对Google Reader中文用户来说,更有价值的是它的同步Google Reader的功能,可以提取出条目的标题和插图以及正文摘要,并以一定的热度排版,并连接了几家最流行的SNS服务,可以及时分享自己的条目,自从用了Feedly后,我几乎就不用Google Reader的官方界面了(喂喂,你是他们的托儿啊)。
再说回Twitter客户端,目前现在的客户端,基本上都是简单地通过Twitter API将Twitter的Tweet功能从Web搬到桌面或手机端等,几乎没有做更多的需求挖掘。简单地看过几十个完成度较高的Twitter客户端,目前只看到Seesmic Look收集了几组全球知名媒体的账号,但也仅仅是收集,没有更多的特性拓展。现在Twitter推出了新版界面,可以说是诠释了Twitter自己的发展理念,引领了客户端发展的方向──它提供的是新闻,是内容,是信息!
最后可以得出,我想要的客户端,是融合了FlipBoard、http://paper.li/和Feedly几者特色的客户端。它一方面可以向用户提供类似传统书报媒体提供给用户的视觉感观享受,另一方面则是结合网络、计算机的优势,提供大容量、快捷的信息分享功能。所以它不应该只像FlipBoard、http://paper.li/和Feedly它们一样只有一两家内容提供商,它应该是彻底开放的,允许其他内容提供商以固定的接口接入并提供特有的信息。而且它应该有一定的信息自动分类和索引能力,过滤重复或无价值信息,减少用户浪费的时间。
Tag dmg
今天觉得Ninayan大部分功能已经实现了,也差不多快可以发布beta版了,于是要打包,先解决Windows和Mac上的打包问题。 Windows上一直以来我都习惯用Inno Setup了,所以在如何制作安装包的问题上并不纠结,InnoIDE和ISTool都是很方便的工具,主要的问题在于解决Qt的插件的部署。Ninayan在Windows上也是用GCC(MinGW)编译的,相比VS2008,少了个SxS的问题,只要带两个dll一起发布就行了。Qt本身有一种简单但比较有用的插件机制,它的字符编码支持CJK,图形文件格式支持,数据库驱动等等都是由插件实现的。也就是说$(QTDIR)/plugins下的东西都要跟着发布,而且程序代码中需要自己在main()中,app对象创建后及时调用QCoreApplication::addLibraryPath()添加plugins的路径。另外由于用到了QtWebKit和QML,QDeclarativeEngine对象也需要指定一下qmlwebkitplugin插件的目录,把$(QTDIR)/imports/QtWebKit目录打包进去,然后在代码中调用QDeclarativeEngine::addImportPath()添加路径,这样整个目录就是发布的所有内容了。 在Mac OSX上比较流行用dmg,但这之前还要解决Qt的framework链接的问题。Qt在Mac OSX下官方发布的二进制包是framework形式的,这跟Windows下有点不同,呃,其实跟SxS有点类似。要用install_name_tool -change命令行修改自己的程序可执行文件链接的framework的位置,这个工作可以由Qt自带的一个叫macdeployqt的小工具完成,只要在命令行执行macdeployqt Ninayan.app就可以了。不过除此之外,还是由于qmlwebkitplugin的缘故,需要自己复制这个插件到程序的bundle中,我就放在跟最终的可执行文件相同的目录中,这个插件macdeployqt并不处理,除了要自己复制,还要自己用install_name_tool来修改链接的framework。这样操作后,是一个可以正常运行的,完整的应用程序bundle,整个bundle就有113MB,谁让Qt那么大呢!然后是把这个bundle打包成dmg。Mac OSX自带免费的工具,GUI和CUI的都有,GUI的叫Disk Utility,不过看了下感觉界面挺复杂的,还是用命令行的hdiutil爽,而且我前面是用命令行修改的符号链接,这里当然最好也是用命令行打包,这样一个shell脚本就能搞定编译后生成dmg的所有事情了。用hdiutil的话,这个命令行就可以打出一个dmg来: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDZO -ov Ninayan.dmg 不过这个有点土,就是把Ninayan.app放成了dmg而已,其他什么都没有。我的要求其实也很简单,有自定义的背景图片,有Applications目录的链接,这样用户打开这个dmg就可以完成把Ninayan拖拽到Applications目录中的操作。在网上找了不少文章和视频,多是用其他的GUI工具,在stackoverflow上有个家伙用AppleScript写了段脚本,确实通用性和灵活性都比较好了。最后我选了条简易简陋没通用性的路子,但够用。首先需要明白的是,dmg被Finder打开后,就是当成一个普通的文件夹处理的,所以它的背景什么的设置,都是放在.DS_Store文件中的(Mac中以dot开头的文件都会自动隐藏),所以很dirty的做法是,先用这个命令行创建一个可读可写的dmg并挂载: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDRW -size...
Tag Mac
最近想着赶紧弄个程序出来上架到Mac App Store去,因为我只会用Qt写Mac的GUI程序,所以要研究一下如何把Qt程序签名上架,结合网上找到的这篇、这篇,以及这篇文章,折腾了几天了,最终,仍然没搞定怎么签能上架Mac App Store的Qt程序,貌似只搞定了Developer ID类型的,即在Mac App Store以外发布的程序,这种签名唯一的用处貌似是别人拿去能直接运行而不会弹出个消息框说来自不受信任的开发者(其实我是猜的,没验证过。
今天觉得Ninayan大部分功能已经实现了,也差不多快可以发布beta版了,于是要打包,先解决Windows和Mac上的打包问题。 Windows上一直以来我都习惯用Inno Setup了,所以在如何制作安装包的问题上并不纠结,InnoIDE和ISTool都是很方便的工具,主要的问题在于解决Qt的插件的部署。Ninayan在Windows上也是用GCC(MinGW)编译的,相比VS2008,少了个SxS的问题,只要带两个dll一起发布就行了。Qt本身有一种简单但比较有用的插件机制,它的字符编码支持CJK,图形文件格式支持,数据库驱动等等都是由插件实现的。也就是说$(QTDIR)/plugins下的东西都要跟着发布,而且程序代码中需要自己在main()中,app对象创建后及时调用QCoreApplication::addLibraryPath()添加plugins的路径。另外由于用到了QtWebKit和QML,QDeclarativeEngine对象也需要指定一下qmlwebkitplugin插件的目录,把$(QTDIR)/imports/QtWebKit目录打包进去,然后在代码中调用QDeclarativeEngine::addImportPath()添加路径,这样整个目录就是发布的所有内容了。 在Mac OSX上比较流行用dmg,但这之前还要解决Qt的framework链接的问题。Qt在Mac OSX下官方发布的二进制包是framework形式的,这跟Windows下有点不同,呃,其实跟SxS有点类似。要用install_name_tool -change命令行修改自己的程序可执行文件链接的framework的位置,这个工作可以由Qt自带的一个叫macdeployqt的小工具完成,只要在命令行执行macdeployqt Ninayan.app就可以了。不过除此之外,还是由于qmlwebkitplugin的缘故,需要自己复制这个插件到程序的bundle中,我就放在跟最终的可执行文件相同的目录中,这个插件macdeployqt并不处理,除了要自己复制,还要自己用install_name_tool来修改链接的framework。这样操作后,是一个可以正常运行的,完整的应用程序bundle,整个bundle就有113MB,谁让Qt那么大呢!然后是把这个bundle打包成dmg。Mac OSX自带免费的工具,GUI和CUI的都有,GUI的叫Disk Utility,不过看了下感觉界面挺复杂的,还是用命令行的hdiutil爽,而且我前面是用命令行修改的符号链接,这里当然最好也是用命令行打包,这样一个shell脚本就能搞定编译后生成dmg的所有事情了。用hdiutil的话,这个命令行就可以打出一个dmg来: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDZO -ov Ninayan.dmg 不过这个有点土,就是把Ninayan.app放成了dmg而已,其他什么都没有。我的要求其实也很简单,有自定义的背景图片,有Applications目录的链接,这样用户打开这个dmg就可以完成把Ninayan拖拽到Applications目录中的操作。在网上找了不少文章和视频,多是用其他的GUI工具,在stackoverflow上有个家伙用AppleScript写了段脚本,确实通用性和灵活性都比较好了。最后我选了条简易简陋没通用性的路子,但够用。首先需要明白的是,dmg被Finder打开后,就是当成一个普通的文件夹处理的,所以它的背景什么的设置,都是放在.DS_Store文件中的(Mac中以dot开头的文件都会自动隐藏),所以很dirty的做法是,先用这个命令行创建一个可读可写的dmg并挂载: hdiutil create -srcfolder Ninayan.app -volname Ninayan -format UDRW -size...
Tag Cocoa Touch
今天彻底打酱油了,我们shared dev team也只剩下我,老大和Jason三个人了。因为晚上2点才睡,才睡了不到6个小时,于是下午就坐在办公椅上睡了近1个半小时,最后是被他们讨论一个bug的声音吵醒的,啊哈哈,老大还说让我看一下,现在只有我在这方面有经验了,我囧,我完全没经验的说,后来还是Sherman厉害啊! 再后来,就跟老大讨论了一会儿C++ singleton的实现,以及跨DLL数据引用等等。问题是有个Watson的bug,我从一次crash的call stack中发现,程序在调用_exit后,该程序中的static object应该是已经瞬间被无声息地干掉了,所谓无声息的,就是说,连它的析构函数都没被调用的。但这时嵌入的CLR还需要做一部分扫尾的工作,而恰恰是这扫尾工作又反过来调用了那个貌似已经被干掉的static object,于是程序crash了。当然这只是我的猜测,我猜测嵌入的CLR就是要生存周期长一点,于是一直在代码中试图找一下它是怎么从C++端嵌入CLR的,然后怎么用CLR的。我发现的情况貌似是这样的,先用Managed C++写了一个dll,这个dll可以在DllMain,还可以导出函数,而据我前些天才知道的知识,.NET编写的普通的DLL形式的assembly跟原本的DLL不一样,没有DllMain的。而这个DLL通过导出函数返回一个对象的指针,这个exe程序通过GetProcAddress获取导出函数,再调用这导出函数获取对象指针。这个返回的对象呢,是个CLR Bridge,也就是说,通过这个对象,可以从C++端创建CLR中的对象,调用CLR对象中的方法等等。也就是说,从代码中,我没看到Jeffray Richter在《CLR via C#》中说的那种CLR host的方法。现在我仍然在怀疑,是不是我代码没看全,但我确实之前也在整个代码目录下搜索文本,没有那几个用于host CLR的API调用。似乎有点跑题了。然后我就跟老大说了一下我发现的这些情况,略微讨论了一会儿,老大表示自己也不知道,唔,其实我也不指望他知道,只是有这么一种想跟人分享自己的发现的欲望而已。基本上,我就觉得这很可能是此bug的root cause了,但老大说可能只是个cause,而不是root cause,好吧,其实就是缺少验证而已。一个比较有说服力的验证方法是自己用C++写个小程序,然后用相同的方法调用CLR中的代码,最后能制造出同样的crash,只是我最近木有动力去做这些事而已。另外就是,即使确定了这是个root cause,简单地说来,这个root cause应该就是对象销毁的顺序不对,这是可以肯定的,但之后也不好fix,因为这个程序实在太庞大了,有很多对象,然后引用关系也很复杂,以我目前对它的了解程度,根本没能力对理顺这个关系,于是也就fix不了了。而且还有个另外的问题是,那个static object是该程序中用于实现singleton的一种方式,我觉得比较奇怪,老大说,这是为了应付多线程的情况。还有种应用多线程的singleton实现方式是在create instance时加锁,唔。关于这个话题,在前段时间看到TopLanguage group中有个讨论,提到boost中某个库中的singleton实现,貌似很干净的实现,不用锁,也不是static object,能适应多线程,囧,具体的不记得了,貌似boost中有好几个子库中都有自己的singleton的实现,得再去看看代码才行,另外好像《Modern C++ Design》里也有对多线程singleton实现的讨论,春节放假看看去。 话说,今天还看到Mono,发现除了有Mono Touch外还有Mono for Android,不过免费试用版都只能在emulator上跑,最便宜的个人版license也要399刀。不禁大骂Qt的不给力,为毛只能为Symbian和MeeGo用,Android port至今还在alpha...
终于大体上对iOS有一个模糊的轮廓了,做一个没有特别的技术点或者奇异的UI的app的话,基本上靠翻书和查手册应该能搞定了,就像几个月前开始用QML写Ninayan一样。
昨天被ObjC和Cocoa Touch给联合调戏了,我居然以为任何对象都可以随便release。实际上release了不该release的对象后,就会出现各种古怪的问题。
另外有件让我觉得比较蛋疼的事,苹果居然为了用ObjC实现一个singleton而提供了一段官方的样板代码,囧死了。
Tag iOS
这个app在2014年就上架过,除了一开始送出去一堆兑换码以外,以每月大约不到1个付费用户的速度卖出过几份。后来也就更新过1个版本,后来就懒得更新了,直到2017年10月因长期不更新被下架了。
自从知道怀孕28周起要数胎动,我就花了几天时间写了个简单的app给老婆数胎动用。
之前在做的滚球推荐app只能在Android上分发,后来想想还是咬咬牙提交到Apple App Store试试,不过还是做好了被拒的心理准备的,因为照以前的经验,这个App有两个可能的原因很明显会被拒,一个是功能太简单,基本上只是浏览一个表格而已,另一个则是用户付费的功能,因为Android系统在国内收费不易的情况下,我就一直懒得做,只是放了个页面说明,让用户加我们的QQ/微信来通过微信或支付宝等国内流行的移动支付方式来收费。
Qt for Mobile默认是用了一张纯黑的图片作为程序启动图片,所以一开始程序启动时会出现1到几秒的黑屏,机器越慢,这个时间越长,比较不美观,我们可以自己动手设置上适合的图片。
前些天想着给istkani在Android集成个push notification,用了腾讯的信鸽,结果在进程退出后老是会弹框说进程意外结束云云,于是就放下了。
昨天又折腾了大半天iOS Push Notification的证书,之前也折腾过一次,真是麻烦,网上的文章大多步骤相似却不能只靠文章中的步骤得到能用的证书。这里暂且记一下。
2011年买的iPad2服役3年多了,一直用得不错,我当初买其实就图个新鲜感,新鲜劲一过就没什么兴趣了。妹子来了后,就几乎成了她的专属看片工具了。毕竟是款比较老的机型了,在iOS出8后,我就没再升级了,一直停留在7,因为7我都感觉比以前慢了不少,我怕8会使得机器更慢。
先看一遍Apple的官方文档或者网上随便找个入门介绍文章,知道代码主要要做的是在AppDelegate里开头做点初始化工作,然后实现几个函数。Qt对各个平台底层都做了良好的抽象和封装,好在有人做过些相关的研究,可以自己写个AppDelegate替换掉原来的那个。那块代码抄过来后,要注意的是因为我们替换原有的AppDelegate已经过了didFinishLaunchingWithOptions的时机,所以我们在自己的AppDelegate里写一些初始化的代码在didFinishLaunchingWithOptions里是没用的,我的办法是在替换AppDelegate后再做那些初始化工作。但是另外带来些问题,原来写在didFinishLaunchingWithOptions里的一些代码是可以work的,写到其他地方时可能就直接crash了,比如以下这些代码:
之前说过想用Intel C++编译Qt来着,于是从VeryCD上找到Windows、Mac和Linux的Intel C++安装镜象不辞辛苦地下载下来安装。结果让人很沮丧啊。
在Windows 7中,无论编译64位版本还是32位版本,都会编译失败,我怀疑是因为Intel C++用了Visual C++的头文件引起的问题,但是我直接用MSVC2010来编译64位的Qt,虽然也是编译失败,却跟Intel C++报的错误不同,好像C++11标准的问题,在Webkit部分中有类名为nullptr,这个名字在C++11中作为保留字了。也不知道那些用MSVC2010编译成功的是用了什么参数。至于使用MSVC2008的配置,我就没兴趣编译了,因为我不喜欢MSVC2008的SxS。
然后在Mac中编译,32位版本也是编译失败,64位版本编译倒是全部通过了,但貌似make install不完整,那些头文件就没有复制过去,还缺了些什么不知道,反正直接把Qt源代码目录中的include目录复制过去是不能用的。于是也放弃了。
后来么,在Windows上下载了32位和64位的TDM GCC,编译了两个晚上才编译出来,话说那个-nomake "demos examples docs"参数不起作用啊。试了试编译Ninayan 64位,可以运行。
这两天看到Nokia的Qt论坛上有个叫Qt4iOS的人,说他做的Qt for iOS插件就要可以正式发布了,好期待啊。又看到有人说,Necessitas虽然还在Alpha版本,但已经可用性很高了,我看了下,现在居然已经提供4.8.0版本的for Windows/Mac/Linux的SDK了。不过在Mac上安装好后想编译Ninayan才发现,源代码还需要做些修改,比如源代码中通过预定义宏只识别了Windows/Mac/X11/Symbian/Maemon,但是这个Android不知道是什么宏,不知道上哪去查点资料看看。
于是最近还在网上看到的消息,是说Windows Phone的下个版本会支持C++开发,如果这样的话,Qt也会很快就支持WP开发。啊,如果Qt真能用于Android、iOS和Windows Phone的开发,那就太牛逼了。说实话,如果这些port的质量可以的话,只要价格不是太离谱,我应该会买这license去的。
今天彻底打酱油了,我们shared dev team也只剩下我,老大和Jason三个人了。因为晚上2点才睡,才睡了不到6个小时,于是下午就坐在办公椅上睡了近1个半小时,最后是被他们讨论一个bug的声音吵醒的,啊哈哈,老大还说让我看一下,现在只有我在这方面有经验了,我囧,我完全没经验的说,后来还是Sherman厉害啊! 再后来,就跟老大讨论了一会儿C++ singleton的实现,以及跨DLL数据引用等等。问题是有个Watson的bug,我从一次crash的call stack中发现,程序在调用_exit后,该程序中的static object应该是已经瞬间被无声息地干掉了,所谓无声息的,就是说,连它的析构函数都没被调用的。但这时嵌入的CLR还需要做一部分扫尾的工作,而恰恰是这扫尾工作又反过来调用了那个貌似已经被干掉的static object,于是程序crash了。当然这只是我的猜测,我猜测嵌入的CLR就是要生存周期长一点,于是一直在代码中试图找一下它是怎么从C++端嵌入CLR的,然后怎么用CLR的。我发现的情况貌似是这样的,先用Managed C++写了一个dll,这个dll可以在DllMain,还可以导出函数,而据我前些天才知道的知识,.NET编写的普通的DLL形式的assembly跟原本的DLL不一样,没有DllMain的。而这个DLL通过导出函数返回一个对象的指针,这个exe程序通过GetProcAddress获取导出函数,再调用这导出函数获取对象指针。这个返回的对象呢,是个CLR Bridge,也就是说,通过这个对象,可以从C++端创建CLR中的对象,调用CLR对象中的方法等等。也就是说,从代码中,我没看到Jeffray Richter在《CLR via C#》中说的那种CLR host的方法。现在我仍然在怀疑,是不是我代码没看全,但我确实之前也在整个代码目录下搜索文本,没有那几个用于host CLR的API调用。似乎有点跑题了。然后我就跟老大说了一下我发现的这些情况,略微讨论了一会儿,老大表示自己也不知道,唔,其实我也不指望他知道,只是有这么一种想跟人分享自己的发现的欲望而已。基本上,我就觉得这很可能是此bug的root cause了,但老大说可能只是个cause,而不是root cause,好吧,其实就是缺少验证而已。一个比较有说服力的验证方法是自己用C++写个小程序,然后用相同的方法调用CLR中的代码,最后能制造出同样的crash,只是我最近木有动力去做这些事而已。另外就是,即使确定了这是个root cause,简单地说来,这个root cause应该就是对象销毁的顺序不对,这是可以肯定的,但之后也不好fix,因为这个程序实在太庞大了,有很多对象,然后引用关系也很复杂,以我目前对它的了解程度,根本没能力对理顺这个关系,于是也就fix不了了。而且还有个另外的问题是,那个static object是该程序中用于实现singleton的一种方式,我觉得比较奇怪,老大说,这是为了应付多线程的情况。还有种应用多线程的singleton实现方式是在create instance时加锁,唔。关于这个话题,在前段时间看到TopLanguage group中有个讨论,提到boost中某个库中的singleton实现,貌似很干净的实现,不用锁,也不是static object,能适应多线程,囧,具体的不记得了,貌似boost中有好几个子库中都有自己的singleton的实现,得再去看看代码才行,另外好像《Modern C++ Design》里也有对多线程singleton实现的讨论,春节放假看看去。 话说,今天还看到Mono,发现除了有Mono Touch外还有Mono for Android,不过免费试用版都只能在emulator上跑,最便宜的个人版license也要399刀。不禁大骂Qt的不给力,为毛只能为Symbian和MeeGo用,Android port至今还在alpha...
盼Qt移植到Android和iOS上是有点盼不到了,尽管都有开源社区的人在进行相关的工作,但实在进度太慢,等不及了。还是老老实实去学JAVA和Android SdK,Objective-C和Cocoa Touch吧。
昨天花了半个晚上,在Windows XP SP3和Mac OS X 10.6.7上配置好了Android开发环境。安装配置的过程非常简单,基本上每本讲Android开发的书上都有会那么些篇幅讲这些内容,而作为开源工具集合而成的开发方案,能做到这样程度的方便,已经相当不错了。而且Android开发环境中有一点我觉得非常厚道的是,它的emulator可以直接安装正式发布的app的apk包来运行,这给开发者带来极大的便利,可以直接体验别的app,而且不用担心有害代码。而无论是iOS还是Symbian都不行。
今天下午在网上找了一下Xcode4版本无证书进行真机调试的信息,还真的找到一篇文章,操作也不是很复杂,最后在我的Xcode 4.0+Mac OS X 10.6.7+Touch 4.3.3环境中实验成功,真是开心啊。
这样基本上解决了Android和iOS开发的绝大部分问题,至少deployment是基本解决了。开始移植Ninayan吧。
回家了,可能还是因为长假的缘故,两个收费站都堵了好久,几乎每个服务区里加油的车都是排长队的。
下午又看了一遍goagent for iOS的wiki page,然后开始折腾。花了约2个小时把touch装上了goagent,感觉就是速度似乎比GFWInterceptor要慢,其他没什么区别。晚上又折腾了下,把iPad也装上了goagent,这样Flipboard可以添加上Facebook账号了。好像换了goagent唯一的好处是可以比较完美地上Facebook了,囧。嗷嗷嗷,更想去弄个Android机了!
让我觉得比较郁闷的是,在Mac OS X上用goagent,似乎添加的SSL证书不起作用。于是Ninayan在Mac上就不能连接Twitter了,纠结了。
这些天发现可以通过MS Exchange把Google Calendar,Google Contacts和Gmail同步到iOS设备上,还可以同步到Nokia C7上,于是一直在折腾。
有时候同步会有延时,还有,发现如果Google Contacts里的生日只填月日,不填年份的话,貌似不能正常识别并使用,比如在iOS上会把联系人的生日那天在Calendar上标记出来,但没有年份的话是不会标记的,因为压根没有从Google Contacts同步过来。
除了联系人和日历外,邮件也是很有用的,用Exchange在线维护感觉很好,不过本来想的是Gmail可以通过pop3来收取其他邮箱的邮件,但是很头痛的发现它连接不到网易邮箱的pop3服务器,总是报连接超时,但连接hotmail没有问题,而用hotmail通过pop3连接网易邮箱又是可以的!这谷歌和微软在对华公关上做得差距有点大,当然可能是因为微软是得罪不起,而谷歌没这么不可或缺。于是只好先用hotmail把网易的邮件收下来,再用Gmail把hotmail都收过来,然后根据收件人把邮件打上不同的label。
另外有个问题是,我在电脑上,无论是XP还是Mac上都配置不好客户端的Exchange连接,Outlook 2003,Foxmail 7.0以及Mac Mail,都说连接不上m.google.com,这就很头痛了!要继续研究下。
终于大体上对iOS有一个模糊的轮廓了,做一个没有特别的技术点或者奇异的UI的app的话,基本上靠翻书和查手册应该能搞定了,就像几个月前开始用QML写Ninayan一样。
昨天被ObjC和Cocoa Touch给联合调戏了,我居然以为任何对象都可以随便release。实际上release了不该release的对象后,就会出现各种古怪的问题。
另外有件让我觉得比较蛋疼的事,苹果居然为了用ObjC实现一个singleton而提供了一段官方的样板代码,囧死了。
Tag ObjC
终于大体上对iOS有一个模糊的轮廓了,做一个没有特别的技术点或者奇异的UI的app的话,基本上靠翻书和查手册应该能搞定了,就像几个月前开始用QML写Ninayan一样。
昨天被ObjC和Cocoa Touch给联合调戏了,我居然以为任何对象都可以随便release。实际上release了不该release的对象后,就会出现各种古怪的问题。
另外有件让我觉得比较蛋疼的事,苹果居然为了用ObjC实现一个singleton而提供了一段官方的样板代码,囧死了。
Tag love
清早醒来,看到一条推,于是连吃早饭都没有心情了。
其实吧,长久以来,我都是一直在纠结,为着同一个问题而苦恼。
对于爱情,我缺少在其他方面一直拥有的勇往直前的勇气和信心。
尽管很多时候安慰自己,没有就没有吧,不行就算了,随便吧。可是实际上,每次当确实地看到什么,确信地以为她将远去,心就非常的痛。
每当心情不平静的时候,就什么事都不想做了。连敲键盘的手,都是那么重。
各种的没有动力啊。
Tag muer
今天木耳手机被偷了,中午吃饭时还看她在4sq上check in酸奶店,吃完饭回到办公位上看了一下timeline,就看她在说手机被偷了,现在的小偷真是无所不偷啊,那么小屏幕的,成色也不新的手机也偷,真是穷怕了。据说还是在她学校门口,买酸奶,刚刚还在GT聊天的,一秒种就没了。
然后木耳回家了,貌似没带电脑,于是突然好像人间蒸发了。
下午突然想暂时不移植Ninayan到Android上去了,深入研究下LaTeX吧,对自己无语了。
昨晚打电话,语气之冷淡之客套,太让我失望了。最卑贱不过感情,最凉不过人心。
给自己算了一下,我每天有12个小时不是在上班就是在上班路上,剩下12个小时里8小时要睡觉,剩下4小时里1小时用于洗漱清洁,剩下3小时里有2小时要去阿玛尼或原力健,最后剩下1小时要追小说。确实没时间做其他事啊,这样的日子难道我要一直过下去,直到垂垂老去?太可怕了ヽ(*。>Д
感觉我现在有很多想要做甚至必须做的事,可是很杂乱,我觉得我需要把这些事情理一理。首先,需要定好目标,而且目标是按时间来排序的,半年后一年后两年后三年后五年后需要达到什么目的。然后根据目标制订计划,为了达到这些目标,需要做些什么事。这样可以把现在想的那些杂乱无章的事情都填进去。
自从开始用Google Calendar后,感觉还不错,关键是除了web界面外还可以通过MS Exchange协议同步到手持设备上去,而且跟联系人和邮箱绑定,很方便,之前用doit.im其实感觉也还可以,但是它不能同步到我的C7上。不过Google Calendar貌似只能同步一个Calendar到iOS和Anna上,不知道Android上什么情况,真想弄个Android机玩玩。
基本上确认了,Ninayan不能使用goagent是SSL证书的问题。本来Ninayan用的是Qt4.6中带的证书,而goagent自己又带了证书,可能两个冲突了,修改一下Ninayan,让它不使用Qt 4.6的证书,就能使用goagent代理了,这就比较头痛了。问题是原来在Ninayan中使用Qt 4.6的证书是因为有的系统上的SSL证书不全,Ninayan会不能正常访问一些https地址,可是现在却又要去掉,囧。
今天老大做了个Design Patterns in XXX,这个XXX是他最近几个月来写的一个小工具,走马观花地讲了Template Method,Factory,Strategy和Facade,感觉吧这些模式是怎么回事还是懂的,跟复习了一遍差不多,不过我写代码时其实很少考虑要用什么模式,叹气。
昨天拍的集体照,今天看到了,我怎么胖成这样,上次跟bobo见面时被bobo说了句“你怎么胖成这样?”我还觉得是不是有点夸张,现在自己看到了,一比较,才发现真的好胖,尤其是脸都变形了,减肥刻不容缓啊。惆怅。
早上照例翻看了点东西,然后悲剧了。悲剧归悲剧,反而有点解脱的感觉。精神洁癖偶尔也有点好处,叹气。
早上惊闻木耳的twitter账号注销了,倒不是非常意外,微微失落之余,反而隐隐有点高兴,这丫头终于有多的时间可以用来复习准备考研了。
晚上回来,习惯性地打开木耳的页面,居然发现这丫头还是跟平常一样在唠,看了一下才发现原因,打电话确认了一下,真是替她感到高兴。
不过也有难过的事,居然说我变心快,这丫头就是疑神疑鬼太厉害了,都半年了一直这样。倒是我想回敬她这句话的。怎么她这个白羊女跟双鱼男一样的严重缺乏安全感啊。别说快了,明明连变都没有变,明明是我这两个月来精神被折磨得支离破碎。
我以前都说过了,我总是爱屋及乌恨屋及乌并夸大影响,但人们都只注意到了前一个词,却不留心我特意加上的后一个词。
好好赚钱,好好享受,一定要记住这黎明前最黑暗的日子。
今天墨墨晓晓和木耳过来七宝,也没有什么玩的。
中午去老街里面吃汤圆,然后回到我住处,4个人这么呆坐了一下午,各自上推,除了晓晓玩了会儿游戏。不是自己的地方,果然怎么都弄不出那种味道来,连电视都没有接有线电视或数字电视。
到五点就去接头暗号吃烤肉,39块钱一人,一桌再加3块钱酱料钱,实在很优惠了。吃了2个小时,撑到了!
然后就送他们到地铁站。
又想起《水果篮子》那句经典的话。
当意识到两人因为价值观的差异而常常意见相左,甚至引发更大冲突时,就会觉得这世界啊,挺没意思的,这人生啊,也挺没意思的。
每个人都常常只认定自己是对的,也许会出于客套听人说人家善意的意见,但心中也许就是不屑。
其实啊,真的挺没意思的。
最近发生了不少事。首先,我找了个工作,在上海,于是又跑到上海来了。这工作倒目前为止给我的感觉应该是比较轻松的。租房子离上班的地方比较远,每天开车来回要2个小时左右。
然后我又如去年那样悲剧了一把,真不知道是我有问题还是对方有问题。上海啊,真是我的哀伤之地。
最后,历经2周,昨天终于把宽带装好了,上海电信的服务实在太差了。这个小区是光纤接入,这上门装的设备还带一个无线路由器。这路由器貌似同一时刻只能有一个客户连接,没找到设置界面,而且touch和ipad连接上后,是上不了网的。换成自己的TPLink后就一切正常了。对的,上周末去败了个最低配的iPad2。
到了上海,算是有了新的开始,终于有机会真正向纸醉金迷的生活迈进了,要好好享受人生啊,人活一世机会难得。平时就好好上班,晚上回来继续搞,嗯,现在不是专职了,只能算外快了,周末就尽量出去玩玩,那些景点要去走个遍。
你也许不相信,我淡推,我不发短信,我不打电话,我不去找你,很大一部分原因是因为我不想打扰你学习,尽管可能是我高估了自己。
清早醒来,看到一条推,于是连吃早饭都没有心情了。
其实吧,长久以来,我都是一直在纠结,为着同一个问题而苦恼。
对于爱情,我缺少在其他方面一直拥有的勇往直前的勇气和信心。
尽管很多时候安慰自己,没有就没有吧,不行就算了,随便吧。可是实际上,每次当确实地看到什么,确信地以为她将远去,心就非常的痛。
每当心情不平静的时候,就什么事都不想做了。连敲键盘的手,都是那么重。
各种的没有动力啊。
Tag Mobile
从淘宝花了几十块钱买了个Nexus 5的尾插排线,然后自己掰开后盖换上,Nexus 5复活了!有点小遗憾是我的手工不好,换上后不是很紧凑的样子。
周四周五的时候妹子跟我说她的Nexus 5屏幕在抖动,当时我也没放在心上,只想着可能是系统或某个app的缘故,等抽空把数据备份一下,然后还原出厂设置试一下。结果拖延症一拖也就过去了,昨天妹子出去参加什么沙龙去了,晚上回来手机已经抖得几乎没法用了,我就着急想把数据备份一下,主要就是(垃圾)微信聊天记录,照片以及通讯录。结果一插到电脑上,干脆花屏了!然后妹子就大发脾气。
之前给avege的DNS解析功能加了黑名单白名单,然后就直接部署在家里的树莓派上了,昨天晚上突然发现妹子的Nexus 5和我的Nexus 6全都连不上WIFI了,右上角的WIFI图标一直显示着感叹号。换热点,重启路由器,重启手机WIFI开头都没有,我想了想这两天来做的事情,基本确定是因为avege的DNS解析功能导致的。
前些天想着给istkani在Android集成个push notification,用了腾讯的信鸽,结果在进程退出后老是会弹框说进程意外结束云云,于是就放下了。
iPad Mini和Surface都快要发布了,各种消息满天飞,我最关心的当然是价格了,因为作为当今世界上做软件系统最好的两家公司,他们的产品足够吸引我的注意力!
不过iPad Mini最低配的价格貌似还可以接受,Surface的就远远超出我的预期了。叹气啊!但是很可能过段时间仍然咬咬牙上了,再托阿菲帮忙从美国带吧,估计Surface至少比国内买行货少花费500人民币吧。
有个同事,平时看我在公司里用手机连公司的WIFI,很是眼热,一直问我怎么用。我就告诉他,要装个ProxyDroid,而且手机得root先。这样持续了将近1个月,今天他突然跑过来对我说,都怪你都怪你,现在我的手机刷得只剩下闹钟了。原来他的HTC G12昨天被他用什么一键root软件强行root,结果不能启动WIFI了。于是今天中午和另一个同事一直在OF外面折腾这手机,希望能恢复WIFI。结果还是没有什么进展,而且最后从网上看到,似乎他的G12是所谓的木马机,笑死了。
今天看到,豆瓣推出阅读器了,除了Web版和iPad版,毫不意外地有Kindle递送服务。说起Kindle,之前有一段时间我非常想买一个电子书,当时只考虑了1000出头的Kindle3和500左右的Bambook,不过好在每当一有这种强烈的购买欲望时,都有一股理性的声音说,你不是个爱看书的人!然后就拖到现在也没有买。自从上次去上海图书馆,亲自把玩了一会儿Bambook,非常庆幸自己没有一时冲动买了这么个设备,这页面切换的速度太慢了,效果太难看了,版式也很丑,啧啧!不知道Kindle到底怎么样,得找个地方也亲身去体验一下,才能决定到底能不能符合我的要求啊。
昨天又不甘心,在网上一通乱搜,终于找到一个英文固件刷中文的方法,在dospy上有一篇帖子比较详细地介绍了整个过程,还是比较简单的,今天晚上回来搞了一下,其实就几分钟的事,终于搞定啦,内牛满面啊,然后发现Gravity已经过期了,我要去买么,唔。
昨天下午收到了Nokia寄过来的Qt Ambassador Kit,4张Qt的贴纸,2张Qt Ambassador的贴纸,一件黑色的T恤和一部C7手机。从包裹外包装上看,用的是一家叫TNT的快递公司,以前都没听说过。
之后就一直在折腾手机。居然没有说明书,但是有贴膜,显然是被拆过封。接着发现不支持中文,以为要刷机,头痛。后来在dospy上看到如果只是为了支持中文的话,只要装入兼容的字体文件就可以了,终于搞定!
现在我也是有WIFI手机用的人了,啊哈哈!
今天突然在推上看到Nokia N9的消息。搭载了MeeGo 1.2版本,已经很新了。
下午收到了Qt Ambassador的邮件,邀请为N9开发app,还可以申请N950用于调试和测试。可以使用Qt为N9开发应用,对我来说,实在是欣喜,至少Ninayan要移植过去应该障碍很少了。
上官网看了一下大概的情况,官方指导价550欧,有点贵,不过它有3.9英吋的屏幕,而且看截图,真的有点心动。
感觉N9会是一个好玩具。
Tag Nokia
N9作为Nokia推出的唯一一部装载MeeGo系统的手机,主打宣传的是其滑动手势。
滑动手势在其他触摸屏设备上已经有所应用,各种移动操作系统也对其有一定的支持,但在N9上作为主推特性的滑动手势主要是基于Qt这个跨平台的开发框架实现的,因为从实现角度讲,N9装载的MeeGo系统的UI都是建立在Qt的基础之上的。
Qt自从被Nokia收购后,一直致力于在移动设备上的移植工作,尤其是对Symbian的支持越来越多。而MeeGo这个原本由Nokia和Intel合作开发的项目,同样做了很多跟Qt适配的工作。
Qt做了很多为方便实现触摸操作响应的工作,特别是后来推出的Qt Quick,彻底地让UI和业务逻辑分享。美工可以只使用非常简单的脱胎于JavaScript的声明式语言QML来构建UI,而程序员则可以专注于使用C++或JavaScript实现底层的业务逻辑。Nokia为QML提供了非常丰富的UI元素,还为Symbian系统特地实现了一组扩展的UI控件,这已经可以实现绝大多数的UI需求,各种UI元素又可以随意组合从而构建出更加复杂的应用。而且Qt还提供了多种QML与C++交互的机制,如果QML内建的UI元素不能满足实际需求,程序员可以用C++实现复杂的UI,而Qt本身又有基于CSS style sheet的UI方案和Graphics View的方案,这都让开发人员可以快速地制作出炫目的UI来。另外值得一提的是,基本上可见的QML UI元素,都为触摸操作甚至滑动手势提供了一定的支持,这从QML自带的Demo就可以看出来,不但需要的代码量非常少,而且做出的UI效果却非常时尚。
可以这么说,Qt推出Qt Quick这个方案,代表了应用程序开发的一个方向,快速制作精美UI的方向。基本上所有大的开发框架/解决方案都采用了类似的技术,比如微软的WPF,Mozilla的XUL,甚至Qt在开源界的长期竞争对手Gtk+也有类似的方案,即用简单的标记式、声明式的语言构建UI,减少美工们的学习负担和工作量,而使用其他功能强大、便于操控底层的语言实现业务逻辑。相比其他几个竞争对手,整体而言Qt的优势在于跨平台性好,配套的开发工具也一直在进步。但是它必然也有些缺点,比如一直以来Qt的运行效率不高,虽然Nokia收购后这在方面做了大量的努力;前不久Qt又回归了社区,Nokia成为了一个普通的贡献者,这也许会带来发展方向模糊,进度缓慢的问题,比如一直由开源社区在开发的Qt for Android的port,一年多了仍然没能正式发布。
总的说来,Qt是一个构建Windows、Linux、Mac OS X以及Symbian、MeeGo应用的低成本、高效率的解决方案。如果基于lighthouse机制的Android和iOS移植能尽快正式发布,那在普通消费型电子产品平台上,就真的如它的宣传语所说的Code Less, Create More, Deploy Everywhere了!
昨天又不甘心,在网上一通乱搜,终于找到一个英文固件刷中文的方法,在dospy上有一篇帖子比较详细地介绍了整个过程,还是比较简单的,今天晚上回来搞了一下,其实就几分钟的事,终于搞定啦,内牛满面啊,然后发现Gravity已经过期了,我要去买么,唔。
昨天下午收到了Nokia寄过来的Qt Ambassador Kit,4张Qt的贴纸,2张Qt Ambassador的贴纸,一件黑色的T恤和一部C7手机。从包裹外包装上看,用的是一家叫TNT的快递公司,以前都没听说过。
之后就一直在折腾手机。居然没有说明书,但是有贴膜,显然是被拆过封。接着发现不支持中文,以为要刷机,头痛。后来在dospy上看到如果只是为了支持中文的话,只要装入兼容的字体文件就可以了,终于搞定!
现在我也是有WIFI手机用的人了,啊哈哈!
话说,大前天收到Qt Ambassador Program的邮件,说是A free Qt Ambassador Kit is on its way to you! The kit includes: Customized Qt Ambassador Stickers and T-shirt, Qt Stickers and a Nokia C7 Phone. 让我激动了一场。不过也不知道他们是从哪里寄过来的,也没有个快递单号可以让人在网上跟踪一下行程,真纠结啊,以前从Intel索取手册还给个Fedex的网址可以随时在网上看到状态呢,而且记得还在重庆上学那回,人家Fedex深圳的人发邮件来说我地址不详细,我回个电话告诉人家具体地址后,没几天重庆Fedex的人就专门送上门来了,这还只是几本书而已。这次可是有个手机的哇,是2000人民币价值的东东哇,唔,心焦。...
今天突然在推上看到Nokia N9的消息。搭载了MeeGo 1.2版本,已经很新了。
下午收到了Qt Ambassador的邮件,邀请为N9开发app,还可以申请N950用于调试和测试。可以使用Qt为N9开发应用,对我来说,实在是欣喜,至少Ninayan要移植过去应该障碍很少了。
上官网看了一下大概的情况,官方指导价550欧,有点贵,不过它有3.9英吋的屏幕,而且看截图,真的有点心动。
感觉N9会是一个好玩具。
Tag Aokiwen
作为纸醉金迷的生活的开始,随便在网上看了一下上海的景点列表,排在第一位的居然是上海科技馆,恰好我也知道它在某条地铁线上,于是就跑过去了。之前就听别人说过不好玩,去了之后才体会到到底不好玩到什么程度。60块门票实在太不划算了,6块钱才差不多。里面多数是小孩,以及带小孩子来的大人,像我这样的实在很稀奇。封杀之~
今天在公司里把AWD的第一部分快速过了一遍,明天继续看第二部分,争取这周把整本书都过一遍,达到可以用windbg完成基本的调试任务的目标。说到底,最终的目标是要能用windbg分析dump file的目的,虽然以前也做过这种事,但都是囫囵吞枣不求甚解的,这次有机会可以系统的学习下很有用。另外,我想在这公司里,估计以后回过头来看,最大的收获可能是英语的听读能力有大进步吧,可能写和说的能力也会有所提高吧,这将是我最高兴的事。
周末无聊,随便算了一下自己每月的固定开销,吓了一跳,居然这么高,这点工资收入实在不够看,要多久才能攒够买MBP的钱呢,昨天从上海科技馆出来后跑到陆家嘴的苹果专卖店,发现13寸的那款只要11498了,以前印象中是13998的呀,好心动,国庆后一定要入一个。也就是说,光靠这点工资的收入是远远不能支撑我日益膨胀的消费能力和消费欲望了,赚外快呀呀~
csdn上的Qt应用开发大赛奖品好少,不过E7很让我眼馋喵,还剩下一个半月,快速写几个程序试一把。先就已经提上计划好些日子的Aokiwen吧,豆瓣客户端,支持Win/Mac/Linux,以及Symbian。qDou其实已经做得不错了,不过它一开始就是为手机设计的,有些方面不是很舒服。握拳!
Tag windbg
从昨天下午开始check in,到今天下班仍然没有完成,太囧了,什么乱七八糟的东西,叫了组里最有经验的同事,还有build team里的妹汁来定位,仍然没有搞定,昏特了。
倒是另一个分给我的bug,貌似快要被我搞定了。这次这个bug问题出在C++写的内核里,用Visual Studio 2008调试经验死掉,于是刚好用WinDBG来调,除了有点不习惯,其实WinDBG好像稳定多了,也快多了。其实一般在Visual Studio里调试,也就用到断点,单步,查看变量这三板斧,即使一点没有WinDBG的基础,也可以很快transfer过去。然后用Source Insight看代码写代码,好happy!只是如果仅仅用WinDBG做这些事,有点暴殄天物了。可是我不会其他高级用法,唔…
话说上周五的时候让我给team里的人做WinDBG的training,然后我就随便写了几页ppt,忽悠了50分钟,只提到了怎么用WinDBG实现VS中的那些常见的调试任务,至于WinDBG最擅长的memory corruption,resource leak和postmortem debugging全都没提到,然后老大很不满意,唔,其实我这是故意这么安排的,虽然我自己确实对后面三个topics也没有研究,但要循序渐进嘛!
长假后第一天上班,恶补了下.NET Data Access、ADO.NET的基础知识,叫我这样一点都不懂的人给人去培训,汗。今天看《C#高级编程》看了40页,明天继续看XML相关的内容,也是40页。
然后是安排在下下周五给自己team来个WinDBG的培训,这也是赶鸭子上架,其实我现在的水平,只是比他们多看了一两本书而已,实际能力跟他们差不多,只不过是让我负责这一块而已。我估计着这块的内容可以讲两到三次,每次两个小时,大体上可以分为基础知识,事后调试以及结合本项目调试。
今天快下班的时候,老大才告诉我,昨天让我看的那个bug之后随时都会assign给我处理,我囧,我一直以为老大是看我闲着没事干才让我看着玩的,叹气,形势认识不清!
然后么手头一直有一个watson的bug,虽然这类bug是没有时间限制的,但确实没有头绪,如果一直没有fix,总感觉不太好。
昨天么老大还说跟我聊聊,然后说可能马上会让我抽出一部分时间去做培训讲师,囧。一个现实的问题是,公司确实招不到顶尖的优秀毕业生的,所以只好自己派人去,给那些有意向的学生做相关的技术及soft skill的培训,并筛选出符合要求的人来。原来公司是在花桥有个培训基地的,不过现在听老大的意思,不太赞同那个跑去那边培训的方式,好像就只在公司这边搞一下。
今天旁边的同事接到一个bug,跟TTT(Time Travel Tracing)相关,老大就跟我说这是你的一亩三分地啊,我表示听说过这玩意,老大觉得很诧异,这是MS内部的工具啊,我说我一两年前在某个google group上看到有人讨论过,说gdb也有类似的技术。其实啊,我现在倒真想好好学习使用WinDBG,甚至不用VS的JIT debugger,据说高手们,呃,大概只是MS内部的那些变态们,是不用VS JIT debugger的,比如现在我们对口的FTE那个印度佬,据说以前是IE开发组的,声称调试只用WinDBG。叹气。
goagent貌似只是浏览网页表现好啊,我把gtalk的代理设置成goagent就经常连不上。Ninayan也用不了goagent。
好吧,才发现文章少了一篇还是两篇,估计是换服务器时没留意,数据没同步过来。
今天跟老大谈了下,老大说希望我以后主要研究下Dr.Watson这玩意,另外再加一两个features吧。哈哈,我正好对WinDBG比较有兴趣,我想如果能用WinDBG达到像用VS里的JIT-debugger的熟练程度,那用GDB应该也能比较快上手了吧。
不过这里说用Dr.Watson主要是进行postmortem debugging,也就是说对core dump文件进行分析,可是今天发现,这些core dump文件都是mini dump的,没有包含足够的内存数据,比如heap上的东西就查看不了,这比较纠结,而AWD这书基本上讲是的用WinDBG进行live debugging,叹气!
算了,先不管那么多,肯定随着经验的增加,postmortem debugging的水平也会提高的。星期天上卓越把几本关于.NET、C#以及调试和逆向工程的书买来。
今天终于从服务器上找到几个没因为too old而被删掉的core dump文件,于是祭出WinDBG进行分析。
最大的障碍还是对WinDBG不熟,以及对常用的分析方法不了解。
不过发现一个奇怪的事情。程序是在Win API里崩溃的,该API接受两个字符串作为参数,所以一般说来我们可以认为是作为参数的字符串有问题。通过call stack终于找到最早的这两个字符串的出生地,是两个std::wstring,被const_cast强行对.c_str()的返回值进行转换然后传递出去。所以说,如果call stack没有问题的话,应该是这std::wstring对象的问题了。因为从dump文件中看到TCHAR*的值确实是指向一个不知道什么地方的地方,反正dd是看不出来的,于是dt -r查看这两个std::wstring对象,发现其中的其中的ptr域确实就是指向不知道什么地方去了。好了,奇怪的事情被我发现了,这个函数里,有两个std::wstring对象占用的是同一个内存地址!一开始我的直觉是这不可能,难道是dump文件的问题,或者是release buiding优化后就读不到正确的内容了?我看了一下代码,发现这两个对象是存在于不同的scope中的,有不同的生命周期,嗯,这是从C++对象模型的角度的说法,但实际上编译器会怎么实现,我是一点都没头绪的。我跟老大说了一下,他也认为是dump文件的问题,然后我打开第二个core dump文件,发现了同样的问题。于是虽然老大仍然坚持他的意见,我已经有点动摇了。
好奇怪呀呀呀!
作为纸醉金迷的生活的开始,随便在网上看了一下上海的景点列表,排在第一位的居然是上海科技馆,恰好我也知道它在某条地铁线上,于是就跑过去了。之前就听别人说过不好玩,去了之后才体会到到底不好玩到什么程度。60块门票实在太不划算了,6块钱才差不多。里面多数是小孩,以及带小孩子来的大人,像我这样的实在很稀奇。封杀之~
今天在公司里把AWD的第一部分快速过了一遍,明天继续看第二部分,争取这周把整本书都过一遍,达到可以用windbg完成基本的调试任务的目标。说到底,最终的目标是要能用windbg分析dump file的目的,虽然以前也做过这种事,但都是囫囵吞枣不求甚解的,这次有机会可以系统的学习下很有用。另外,我想在这公司里,估计以后回过头来看,最大的收获可能是英语的听读能力有大进步吧,可能写和说的能力也会有所提高吧,这将是我最高兴的事。
周末无聊,随便算了一下自己每月的固定开销,吓了一跳,居然这么高,这点工资收入实在不够看,要多久才能攒够买MBP的钱呢,昨天从上海科技馆出来后跑到陆家嘴的苹果专卖店,发现13寸的那款只要11498了,以前印象中是13998的呀,好心动,国庆后一定要入一个。也就是说,光靠这点工资的收入是远远不能支撑我日益膨胀的消费能力和消费欲望了,赚外快呀呀~
csdn上的Qt应用开发大赛奖品好少,不过E7很让我眼馋喵,还剩下一个半月,快速写几个程序试一把。先就已经提上计划好些日子的Aokiwen吧,豆瓣客户端,支持Win/Mac/Linux,以及Symbian。qDou其实已经做得不错了,不过它一开始就是为手机设计的,有些方面不是很舒服。握拳!
Tag core dump
今天彻底打酱油了,我们shared dev team也只剩下我,老大和Jason三个人了。因为晚上2点才睡,才睡了不到6个小时,于是下午就坐在办公椅上睡了近1个半小时,最后是被他们讨论一个bug的声音吵醒的,啊哈哈,老大还说让我看一下,现在只有我在这方面有经验了,我囧,我完全没经验的说,后来还是Sherman厉害啊! 再后来,就跟老大讨论了一会儿C++ singleton的实现,以及跨DLL数据引用等等。问题是有个Watson的bug,我从一次crash的call stack中发现,程序在调用_exit后,该程序中的static object应该是已经瞬间被无声息地干掉了,所谓无声息的,就是说,连它的析构函数都没被调用的。但这时嵌入的CLR还需要做一部分扫尾的工作,而恰恰是这扫尾工作又反过来调用了那个貌似已经被干掉的static object,于是程序crash了。当然这只是我的猜测,我猜测嵌入的CLR就是要生存周期长一点,于是一直在代码中试图找一下它是怎么从C++端嵌入CLR的,然后怎么用CLR的。我发现的情况貌似是这样的,先用Managed C++写了一个dll,这个dll可以在DllMain,还可以导出函数,而据我前些天才知道的知识,.NET编写的普通的DLL形式的assembly跟原本的DLL不一样,没有DllMain的。而这个DLL通过导出函数返回一个对象的指针,这个exe程序通过GetProcAddress获取导出函数,再调用这导出函数获取对象指针。这个返回的对象呢,是个CLR Bridge,也就是说,通过这个对象,可以从C++端创建CLR中的对象,调用CLR对象中的方法等等。也就是说,从代码中,我没看到Jeffray Richter在《CLR via C#》中说的那种CLR host的方法。现在我仍然在怀疑,是不是我代码没看全,但我确实之前也在整个代码目录下搜索文本,没有那几个用于host CLR的API调用。似乎有点跑题了。然后我就跟老大说了一下我发现的这些情况,略微讨论了一会儿,老大表示自己也不知道,唔,其实我也不指望他知道,只是有这么一种想跟人分享自己的发现的欲望而已。基本上,我就觉得这很可能是此bug的root cause了,但老大说可能只是个cause,而不是root cause,好吧,其实就是缺少验证而已。一个比较有说服力的验证方法是自己用C++写个小程序,然后用相同的方法调用CLR中的代码,最后能制造出同样的crash,只是我最近木有动力去做这些事而已。另外就是,即使确定了这是个root cause,简单地说来,这个root cause应该就是对象销毁的顺序不对,这是可以肯定的,但之后也不好fix,因为这个程序实在太庞大了,有很多对象,然后引用关系也很复杂,以我目前对它的了解程度,根本没能力对理顺这个关系,于是也就fix不了了。而且还有个另外的问题是,那个static object是该程序中用于实现singleton的一种方式,我觉得比较奇怪,老大说,这是为了应付多线程的情况。还有种应用多线程的singleton实现方式是在create instance时加锁,唔。关于这个话题,在前段时间看到TopLanguage group中有个讨论,提到boost中某个库中的singleton实现,貌似很干净的实现,不用锁,也不是static object,能适应多线程,囧,具体的不记得了,貌似boost中有好几个子库中都有自己的singleton的实现,得再去看看代码才行,另外好像《Modern C++ Design》里也有对多线程singleton实现的讨论,春节放假看看去。 话说,今天还看到Mono,发现除了有Mono Touch外还有Mono for Android,不过免费试用版都只能在emulator上跑,最便宜的个人版license也要399刀。不禁大骂Qt的不给力,为毛只能为Symbian和MeeGo用,Android port至今还在alpha...
好吧,才发现文章少了一篇还是两篇,估计是换服务器时没留意,数据没同步过来。
今天跟老大谈了下,老大说希望我以后主要研究下Dr.Watson这玩意,另外再加一两个features吧。哈哈,我正好对WinDBG比较有兴趣,我想如果能用WinDBG达到像用VS里的JIT-debugger的熟练程度,那用GDB应该也能比较快上手了吧。
不过这里说用Dr.Watson主要是进行postmortem debugging,也就是说对core dump文件进行分析,可是今天发现,这些core dump文件都是mini dump的,没有包含足够的内存数据,比如heap上的东西就查看不了,这比较纠结,而AWD这书基本上讲是的用WinDBG进行live debugging,叹气!
算了,先不管那么多,肯定随着经验的增加,postmortem debugging的水平也会提高的。星期天上卓越把几本关于.NET、C#以及调试和逆向工程的书买来。
今天终于从服务器上找到几个没因为too old而被删掉的core dump文件,于是祭出WinDBG进行分析。
最大的障碍还是对WinDBG不熟,以及对常用的分析方法不了解。
不过发现一个奇怪的事情。程序是在Win API里崩溃的,该API接受两个字符串作为参数,所以一般说来我们可以认为是作为参数的字符串有问题。通过call stack终于找到最早的这两个字符串的出生地,是两个std::wstring,被const_cast强行对.c_str()的返回值进行转换然后传递出去。所以说,如果call stack没有问题的话,应该是这std::wstring对象的问题了。因为从dump文件中看到TCHAR*的值确实是指向一个不知道什么地方的地方,反正dd是看不出来的,于是dt -r查看这两个std::wstring对象,发现其中的其中的ptr域确实就是指向不知道什么地方去了。好了,奇怪的事情被我发现了,这个函数里,有两个std::wstring对象占用的是同一个内存地址!一开始我的直觉是这不可能,难道是dump文件的问题,或者是release buiding优化后就读不到正确的内容了?我看了一下代码,发现这两个对象是存在于不同的scope中的,有不同的生命周期,嗯,这是从C++对象模型的角度的说法,但实际上编译器会怎么实现,我是一点都没头绪的。我跟老大说了一下,他也认为是dump文件的问题,然后我打开第二个core dump文件,发现了同样的问题。于是虽然老大仍然坚持他的意见,我已经有点动摇了。
好奇怪呀呀呀!
Tag calendar
昨晚打电话,语气之冷淡之客套,太让我失望了。最卑贱不过感情,最凉不过人心。
给自己算了一下,我每天有12个小时不是在上班就是在上班路上,剩下12个小时里8小时要睡觉,剩下4小时里1小时用于洗漱清洁,剩下3小时里有2小时要去阿玛尼或原力健,最后剩下1小时要追小说。确实没时间做其他事啊,这样的日子难道我要一直过下去,直到垂垂老去?太可怕了ヽ(*。>Д
感觉我现在有很多想要做甚至必须做的事,可是很杂乱,我觉得我需要把这些事情理一理。首先,需要定好目标,而且目标是按时间来排序的,半年后一年后两年后三年后五年后需要达到什么目的。然后根据目标制订计划,为了达到这些目标,需要做些什么事。这样可以把现在想的那些杂乱无章的事情都填进去。
自从开始用Google Calendar后,感觉还不错,关键是除了web界面外还可以通过MS Exchange协议同步到手持设备上去,而且跟联系人和邮箱绑定,很方便,之前用doit.im其实感觉也还可以,但是它不能同步到我的C7上。不过Google Calendar貌似只能同步一个Calendar到iOS和Anna上,不知道Android上什么情况,真想弄个Android机玩玩。
这些天发现可以通过MS Exchange把Google Calendar,Google Contacts和Gmail同步到iOS设备上,还可以同步到Nokia C7上,于是一直在折腾。
有时候同步会有延时,还有,发现如果Google Contacts里的生日只填月日,不填年份的话,貌似不能正常识别并使用,比如在iOS上会把联系人的生日那天在Calendar上标记出来,但没有年份的话是不会标记的,因为压根没有从Google Contacts同步过来。
除了联系人和日历外,邮件也是很有用的,用Exchange在线维护感觉很好,不过本来想的是Gmail可以通过pop3来收取其他邮箱的邮件,但是很头痛的发现它连接不到网易邮箱的pop3服务器,总是报连接超时,但连接hotmail没有问题,而用hotmail通过pop3连接网易邮箱又是可以的!这谷歌和微软在对华公关上做得差距有点大,当然可能是因为微软是得罪不起,而谷歌没这么不可或缺。于是只好先用hotmail把网易的邮件收下来,再用Gmail把hotmail都收过来,然后根据收件人把邮件打上不同的label。
另外有个问题是,我在电脑上,无论是XP还是Mac上都配置不好客户端的Exchange连接,Outlook 2003,Foxmail 7.0以及Mac Mail,都说连接不上m.google.com,这就很头痛了!要继续研究下。
这些天发现可以通过MS Exchange把Google Calendar,Google Contacts和Gmail同步到iOS设备上,还可以同步到Nokia C7上,于是一直在折腾。
有时候同步会有延时,还有,发现如果Google Contacts里的生日只填月日,不填年份的话,貌似不能正常识别并使用,比如在iOS上会把联系人的生日那天在Calendar上标记出来,但没有年份的话是不会标记的,因为压根没有从Google Contacts同步过来。
除了联系人和日历外,邮件也是很有用的,用Exchange在线维护感觉很好,不过本来想的是Gmail可以通过pop3来收取其他邮箱的邮件,但是很头痛的发现它连接不到网易邮箱的pop3服务器,总是报连接超时,但连接hotmail没有问题,而用hotmail通过pop3连接网易邮箱又是可以的!这谷歌和微软在对华公关上做得差距有点大,当然可能是因为微软是得罪不起,而谷歌没这么不可或缺。于是只好先用hotmail把网易的邮件收下来,再用Gmail把hotmail都收过来,然后根据收件人把邮件打上不同的label。
另外有个问题是,我在电脑上,无论是XP还是Mac上都配置不好客户端的Exchange连接,Outlook 2003,Foxmail 7.0以及Mac Mail,都说连接不上m.google.com,这就很头痛了!要继续研究下。
Tag exchange
这些天发现可以通过MS Exchange把Google Calendar,Google Contacts和Gmail同步到iOS设备上,还可以同步到Nokia C7上,于是一直在折腾。
有时候同步会有延时,还有,发现如果Google Contacts里的生日只填月日,不填年份的话,貌似不能正常识别并使用,比如在iOS上会把联系人的生日那天在Calendar上标记出来,但没有年份的话是不会标记的,因为压根没有从Google Contacts同步过来。
除了联系人和日历外,邮件也是很有用的,用Exchange在线维护感觉很好,不过本来想的是Gmail可以通过pop3来收取其他邮箱的邮件,但是很头痛的发现它连接不到网易邮箱的pop3服务器,总是报连接超时,但连接hotmail没有问题,而用hotmail通过pop3连接网易邮箱又是可以的!这谷歌和微软在对华公关上做得差距有点大,当然可能是因为微软是得罪不起,而谷歌没这么不可或缺。于是只好先用hotmail把网易的邮件收下来,再用Gmail把hotmail都收过来,然后根据收件人把邮件打上不同的label。
另外有个问题是,我在电脑上,无论是XP还是Mac上都配置不好客户端的Exchange连接,Outlook 2003,Foxmail 7.0以及Mac Mail,都说连接不上m.google.com,这就很头痛了!要继续研究下。
Tag gmail
这些天发现可以通过MS Exchange把Google Calendar,Google Contacts和Gmail同步到iOS设备上,还可以同步到Nokia C7上,于是一直在折腾。
有时候同步会有延时,还有,发现如果Google Contacts里的生日只填月日,不填年份的话,貌似不能正常识别并使用,比如在iOS上会把联系人的生日那天在Calendar上标记出来,但没有年份的话是不会标记的,因为压根没有从Google Contacts同步过来。
除了联系人和日历外,邮件也是很有用的,用Exchange在线维护感觉很好,不过本来想的是Gmail可以通过pop3来收取其他邮箱的邮件,但是很头痛的发现它连接不到网易邮箱的pop3服务器,总是报连接超时,但连接hotmail没有问题,而用hotmail通过pop3连接网易邮箱又是可以的!这谷歌和微软在对华公关上做得差距有点大,当然可能是因为微软是得罪不起,而谷歌没这么不可或缺。于是只好先用hotmail把网易的邮件收下来,再用Gmail把hotmail都收过来,然后根据收件人把邮件打上不同的label。
另外有个问题是,我在电脑上,无论是XP还是Mac上都配置不好客户端的Exchange连接,Outlook 2003,Foxmail 7.0以及Mac Mail,都说连接不上m.google.com,这就很头痛了!要继续研究下。
Tag google
这些天发现可以通过MS Exchange把Google Calendar,Google Contacts和Gmail同步到iOS设备上,还可以同步到Nokia C7上,于是一直在折腾。
有时候同步会有延时,还有,发现如果Google Contacts里的生日只填月日,不填年份的话,貌似不能正常识别并使用,比如在iOS上会把联系人的生日那天在Calendar上标记出来,但没有年份的话是不会标记的,因为压根没有从Google Contacts同步过来。
除了联系人和日历外,邮件也是很有用的,用Exchange在线维护感觉很好,不过本来想的是Gmail可以通过pop3来收取其他邮箱的邮件,但是很头痛的发现它连接不到网易邮箱的pop3服务器,总是报连接超时,但连接hotmail没有问题,而用hotmail通过pop3连接网易邮箱又是可以的!这谷歌和微软在对华公关上做得差距有点大,当然可能是因为微软是得罪不起,而谷歌没这么不可或缺。于是只好先用hotmail把网易的邮件收下来,再用Gmail把hotmail都收过来,然后根据收件人把邮件打上不同的label。
另外有个问题是,我在电脑上,无论是XP还是Mac上都配置不好客户端的Exchange连接,Outlook 2003,Foxmail 7.0以及Mac Mail,都说连接不上m.google.com,这就很头痛了!要继续研究下。
Tag Patterns
基本上确认了,Ninayan不能使用goagent是SSL证书的问题。本来Ninayan用的是Qt4.6中带的证书,而goagent自己又带了证书,可能两个冲突了,修改一下Ninayan,让它不使用Qt 4.6的证书,就能使用goagent代理了,这就比较头痛了。问题是原来在Ninayan中使用Qt 4.6的证书是因为有的系统上的SSL证书不全,Ninayan会不能正常访问一些https地址,可是现在却又要去掉,囧。
今天老大做了个Design Patterns in XXX,这个XXX是他最近几个月来写的一个小工具,走马观花地讲了Template Method,Factory,Strategy和Facade,感觉吧这些模式是怎么回事还是懂的,跟复习了一遍差不多,不过我写代码时其实很少考虑要用什么模式,叹气。
昨天拍的集体照,今天看到了,我怎么胖成这样,上次跟bobo见面时被bobo说了句“你怎么胖成这样?”我还觉得是不是有点夸张,现在自己看到了,一比较,才发现真的好胖,尤其是脸都变形了,减肥刻不容缓啊。惆怅。
早上照例翻看了点东西,然后悲剧了。悲剧归悲剧,反而有点解脱的感觉。精神洁癖偶尔也有点好处,叹气。
Tag Android
自从知道怀孕28周起要数胎动,我就花了几天时间写了个简单的app给老婆数胎动用。
公司项目里使用SQLCipher用于本地加密存储数据,之前发现在iOS上打开数据库后执行第一条CRUD特别慢,经过几番优化尝试,发现只要在编译选项指定使用Apple Common Crypto,就能比使用OpenSSL提升100倍性能。但是Android平台上也只能使用OpenSSL,性能问题两年多来一直没解决。
今天手头上的Nexus 6通过OTA升级到了Android 7,之后发现几个用Qt写的App显示中文字符全变成方块了。这个问题在当时系统刚升级到6.0时也遇到过,解决办法是自己带一个中文字体,再在程序中指定使用这个中文字体。这是比较繁琐的解决方法,Qt官方也收到了问题报告,只不过修正后的版本还没有发布,但是问题报告下面有人提到了问题代码,所以要自己出个workaround也很容易,只要在自己的程序开头加这么一段代码就可以了:
前些天看到有人移植了SSR Android版,我就顺便看了看代码,结合网上的一篇文章,觉得似乎挺简单的,它(官方也)用Java/Scala写了个外壳和启动VPN service,其他功能是几个用C写的程序共同完成,包括redsocks,tun2socks,ss-tunnel,ss-local,pdnsd。
之前写过一篇文章谈到为Android app设置splash screen,以避免Qt写的app启动时有一段时间黑屏。今天收到一位朋友的email询问,在splash screen之前仍然会有一个黑屏,怎么去除。
Qt for Mobile默认是用了一张纯黑的图片作为程序启动图片,所以一开始程序启动时会出现1到几秒的黑屏,机器越慢,这个时间越长,比较不美观,我们可以自己动手设置上适合的图片。
昨天突然又想在Qt for Mobile中用上Boost,于是先得把Boost编译到iOS/Android上,然后发现了一个叫CrystaX NDK的东西,它本身的可以作为官方Android NDK的替代,不但对标准库和编译器有了一些改进,还包含了预编译好的Boost库。
前些天想着给istkani在Android集成个push notification,用了腾讯的信鸽,结果在进程退出后老是会弹框说进程意外结束云云,于是就放下了。
这两天突然想把istkani在Android跑一下,本来是想集成个腾讯信鸽的推送功能,但是信鸽没集成好(程序老是挂掉),先去调了一下界面的问题。
前些天Google突然宣布中国开发者可以向100多个国家地区发布付费用户,中国开发者注册账号以及收款啥的也都有了极大改进,我本来就一直有想法要在适当的时候注册一个开发者账号的,于是立马冲动地去花了25刀,还把istkani传了上去,不过后来发现一些问题。当初为了买Nexus 5,把这个账号地址设成一个美国地址了,貌似现在这个开发者账号也成了美国的开发者。听说没有办法改成中国的,除非新注册一个账号,囧。发布的app改不了价格,在后台改价格是成功的,但前台看到的价格仍然是老的。不过有一个比Apple App Store方便的地方是,Google Play似乎几乎没审核,发布上传新App的操作也简单得多,之后等几个小时就直接在Google Play里能搜到了。
之前说过想用Intel C++编译Qt来着,于是从VeryCD上找到Windows、Mac和Linux的Intel C++安装镜象不辞辛苦地下载下来安装。结果让人很沮丧啊。
在Windows 7中,无论编译64位版本还是32位版本,都会编译失败,我怀疑是因为Intel C++用了Visual C++的头文件引起的问题,但是我直接用MSVC2010来编译64位的Qt,虽然也是编译失败,却跟Intel C++报的错误不同,好像C++11标准的问题,在Webkit部分中有类名为nullptr,这个名字在C++11中作为保留字了。也不知道那些用MSVC2010编译成功的是用了什么参数。至于使用MSVC2008的配置,我就没兴趣编译了,因为我不喜欢MSVC2008的SxS。
然后在Mac中编译,32位版本也是编译失败,64位版本编译倒是全部通过了,但貌似make install不完整,那些头文件就没有复制过去,还缺了些什么不知道,反正直接把Qt源代码目录中的include目录复制过去是不能用的。于是也放弃了。
后来么,在Windows上下载了32位和64位的TDM GCC,编译了两个晚上才编译出来,话说那个-nomake "demos examples docs"参数不起作用啊。试了试编译Ninayan 64位,可以运行。
这两天看到Nokia的Qt论坛上有个叫Qt4iOS的人,说他做的Qt for iOS插件就要可以正式发布了,好期待啊。又看到有人说,Necessitas虽然还在Alpha版本,但已经可用性很高了,我看了下,现在居然已经提供4.8.0版本的for Windows/Mac/Linux的SDK了。不过在Mac上安装好后想编译Ninayan才发现,源代码还需要做些修改,比如源代码中通过预定义宏只识别了Windows/Mac/X11/Symbian/Maemon,但是这个Android不知道是什么宏,不知道上哪去查点资料看看。
于是最近还在网上看到的消息,是说Windows Phone的下个版本会支持C++开发,如果这样的话,Qt也会很快就支持WP开发。啊,如果Qt真能用于Android、iOS和Windows Phone的开发,那就太牛逼了。说实话,如果这些port的质量可以的话,只要价格不是太离谱,我应该会买这license去的。
今天彻底打酱油了,我们shared dev team也只剩下我,老大和Jason三个人了。因为晚上2点才睡,才睡了不到6个小时,于是下午就坐在办公椅上睡了近1个半小时,最后是被他们讨论一个bug的声音吵醒的,啊哈哈,老大还说让我看一下,现在只有我在这方面有经验了,我囧,我完全没经验的说,后来还是Sherman厉害啊! 再后来,就跟老大讨论了一会儿C++ singleton的实现,以及跨DLL数据引用等等。问题是有个Watson的bug,我从一次crash的call stack中发现,程序在调用_exit后,该程序中的static object应该是已经瞬间被无声息地干掉了,所谓无声息的,就是说,连它的析构函数都没被调用的。但这时嵌入的CLR还需要做一部分扫尾的工作,而恰恰是这扫尾工作又反过来调用了那个貌似已经被干掉的static object,于是程序crash了。当然这只是我的猜测,我猜测嵌入的CLR就是要生存周期长一点,于是一直在代码中试图找一下它是怎么从C++端嵌入CLR的,然后怎么用CLR的。我发现的情况貌似是这样的,先用Managed C++写了一个dll,这个dll可以在DllMain,还可以导出函数,而据我前些天才知道的知识,.NET编写的普通的DLL形式的assembly跟原本的DLL不一样,没有DllMain的。而这个DLL通过导出函数返回一个对象的指针,这个exe程序通过GetProcAddress获取导出函数,再调用这导出函数获取对象指针。这个返回的对象呢,是个CLR Bridge,也就是说,通过这个对象,可以从C++端创建CLR中的对象,调用CLR对象中的方法等等。也就是说,从代码中,我没看到Jeffray Richter在《CLR via C#》中说的那种CLR host的方法。现在我仍然在怀疑,是不是我代码没看全,但我确实之前也在整个代码目录下搜索文本,没有那几个用于host CLR的API调用。似乎有点跑题了。然后我就跟老大说了一下我发现的这些情况,略微讨论了一会儿,老大表示自己也不知道,唔,其实我也不指望他知道,只是有这么一种想跟人分享自己的发现的欲望而已。基本上,我就觉得这很可能是此bug的root cause了,但老大说可能只是个cause,而不是root cause,好吧,其实就是缺少验证而已。一个比较有说服力的验证方法是自己用C++写个小程序,然后用相同的方法调用CLR中的代码,最后能制造出同样的crash,只是我最近木有动力去做这些事而已。另外就是,即使确定了这是个root cause,简单地说来,这个root cause应该就是对象销毁的顺序不对,这是可以肯定的,但之后也不好fix,因为这个程序实在太庞大了,有很多对象,然后引用关系也很复杂,以我目前对它的了解程度,根本没能力对理顺这个关系,于是也就fix不了了。而且还有个另外的问题是,那个static object是该程序中用于实现singleton的一种方式,我觉得比较奇怪,老大说,这是为了应付多线程的情况。还有种应用多线程的singleton实现方式是在create instance时加锁,唔。关于这个话题,在前段时间看到TopLanguage group中有个讨论,提到boost中某个库中的singleton实现,貌似很干净的实现,不用锁,也不是static object,能适应多线程,囧,具体的不记得了,貌似boost中有好几个子库中都有自己的singleton的实现,得再去看看代码才行,另外好像《Modern C++ Design》里也有对多线程singleton实现的讨论,春节放假看看去。 话说,今天还看到Mono,发现除了有Mono Touch外还有Mono for Android,不过免费试用版都只能在emulator上跑,最便宜的个人版license也要399刀。不禁大骂Qt的不给力,为毛只能为Symbian和MeeGo用,Android port至今还在alpha...
有个同事,平时看我在公司里用手机连公司的WIFI,很是眼热,一直问我怎么用。我就告诉他,要装个ProxyDroid,而且手机得root先。这样持续了将近1个月,今天他突然跑过来对我说,都怪你都怪你,现在我的手机刷得只剩下闹钟了。原来他的HTC G12昨天被他用什么一键root软件强行root,结果不能启动WIFI了。于是今天中午和另一个同事一直在OF外面折腾这手机,希望能恢复WIFI。结果还是没有什么进展,而且最后从网上看到,似乎他的G12是所谓的木马机,笑死了。
今天看到,豆瓣推出阅读器了,除了Web版和iPad版,毫不意外地有Kindle递送服务。说起Kindle,之前有一段时间我非常想买一个电子书,当时只考虑了1000出头的Kindle3和500左右的Bambook,不过好在每当一有这种强烈的购买欲望时,都有一股理性的声音说,你不是个爱看书的人!然后就拖到现在也没有买。自从上次去上海图书馆,亲自把玩了一会儿Bambook,非常庆幸自己没有一时冲动买了这么个设备,这页面切换的速度太慢了,效果太难看了,版式也很丑,啧啧!不知道Kindle到底怎么样,得找个地方也亲身去体验一下,才能决定到底能不能符合我的要求啊。
一直想弄个Android机玩玩,虽然说很多厂商都在做,但一直只想过HTC或Nexus系列,现在看Nexus S不到2000块,还有4寸屏就很心动,纠结了几个星期了。周一的时候自以为搞定了那个bug,心情很好,打算好好犒劳一下自己,晚上回来就上淘宝拍了一个。直到周四才收到快递,昨天晚上回来把它root了,然后装了GAEProxy,装上了几个Twitter客户端。
只用了一天,给我的感觉不是很好。周四晚上突然就有点后悔,我哪有那么多时间来折腾这个玩意。在屋里联通的信号很差,对WIFI的接收能力也不怎么样,默认还没有设置Proxy的功能,需要root后装第三方软件才行,屋里那个无线路由器的信号时断时续。流量跑得飞快,昨天晚上到现在10个小时左右,WIFI流量跑了30MB左右,3G流量跑了20MB,这好像是因为用一GAEProxy的缘故,昨天白天10来个小时没用GAEProxy也差不多走了20MB流量。很多app运行了就不能退出了,即使强行杀进程,它也会自动再启动,囧了。
好吧,其实各有各的优点的,比如这样后台Gmail、Google Reader、Twitter等的推送就感觉不错。
盼Qt移植到Android和iOS上是有点盼不到了,尽管都有开源社区的人在进行相关的工作,但实在进度太慢,等不及了。还是老老实实去学JAVA和Android SdK,Objective-C和Cocoa Touch吧。
昨天花了半个晚上,在Windows XP SP3和Mac OS X 10.6.7上配置好了Android开发环境。安装配置的过程非常简单,基本上每本讲Android开发的书上都有会那么些篇幅讲这些内容,而作为开源工具集合而成的开发方案,能做到这样程度的方便,已经相当不错了。而且Android开发环境中有一点我觉得非常厚道的是,它的emulator可以直接安装正式发布的app的apk包来运行,这给开发者带来极大的便利,可以直接体验别的app,而且不用担心有害代码。而无论是iOS还是Symbian都不行。
今天下午在网上找了一下Xcode4版本无证书进行真机调试的信息,还真的找到一篇文章,操作也不是很复杂,最后在我的Xcode 4.0+Mac OS X 10.6.7+Touch 4.3.3环境中实验成功,真是开心啊。
这样基本上解决了Android和iOS开发的绝大部分问题,至少deployment是基本解决了。开始移植Ninayan吧。
Tag Nexus S
一直想弄个Android机玩玩,虽然说很多厂商都在做,但一直只想过HTC或Nexus系列,现在看Nexus S不到2000块,还有4寸屏就很心动,纠结了几个星期了。周一的时候自以为搞定了那个bug,心情很好,打算好好犒劳一下自己,晚上回来就上淘宝拍了一个。直到周四才收到快递,昨天晚上回来把它root了,然后装了GAEProxy,装上了几个Twitter客户端。
只用了一天,给我的感觉不是很好。周四晚上突然就有点后悔,我哪有那么多时间来折腾这个玩意。在屋里联通的信号很差,对WIFI的接收能力也不怎么样,默认还没有设置Proxy的功能,需要root后装第三方软件才行,屋里那个无线路由器的信号时断时续。流量跑得飞快,昨天晚上到现在10个小时左右,WIFI流量跑了30MB左右,3G流量跑了20MB,这好像是因为用一GAEProxy的缘故,昨天白天10来个小时没用GAEProxy也差不多走了20MB流量。很多app运行了就不能退出了,即使强行杀进程,它也会自动再启动,囧了。
好吧,其实各有各的优点的,比如这样后台Gmail、Google Reader、Twitter等的推送就感觉不错。
Tag HTC
有个同事,平时看我在公司里用手机连公司的WIFI,很是眼热,一直问我怎么用。我就告诉他,要装个ProxyDroid,而且手机得root先。这样持续了将近1个月,今天他突然跑过来对我说,都怪你都怪你,现在我的手机刷得只剩下闹钟了。原来他的HTC G12昨天被他用什么一键root软件强行root,结果不能启动WIFI了。于是今天中午和另一个同事一直在OF外面折腾这手机,希望能恢复WIFI。结果还是没有什么进展,而且最后从网上看到,似乎他的G12是所谓的木马机,笑死了。
今天看到,豆瓣推出阅读器了,除了Web版和iPad版,毫不意外地有Kindle递送服务。说起Kindle,之前有一段时间我非常想买一个电子书,当时只考虑了1000出头的Kindle3和500左右的Bambook,不过好在每当一有这种强烈的购买欲望时,都有一股理性的声音说,你不是个爱看书的人!然后就拖到现在也没有买。自从上次去上海图书馆,亲自把玩了一会儿Bambook,非常庆幸自己没有一时冲动买了这么个设备,这页面切换的速度太慢了,效果太难看了,版式也很丑,啧啧!不知道Kindle到底怎么样,得找个地方也亲身去体验一下,才能决定到底能不能符合我的要求啊。
Tag Kindle
昨晚公司,本来都有点不太想去,因为往年的经历开一次年会失一次望,不如回家陪妹子。跟妹子聊起这个事,妹子倒劝我还是去参加吧,抽奖奖品我确实很想要一台带背光的Kindle,家里已有的Kindle4和DXG都没背光,晚上吊顶的灯光不适合看。于是还是去参加了,还当了一回苦力拉了几箱东西,包括所有抽奖奖品去酒店。
抓取网络小说的小程序断断续续有了不少更新,除了支持更多的小说网站外,还有一些值得一提的内容:
前些天突然心血来潮,写了个小程序,用于从网上抓取网络小说,然后生成content.html,content.opf和toc.ncx文件,再放入一个合适的字体文件,比如经过我几番比较,在我的Kindle4上使用方正准圆比较好,最后用kindlegen生成mobi文件,于是可以使用kindle来阅读网络小说了。
一直以来说微信公众号的阅读体验不满意,但是现在越来越多的高质量的文章都发到微信公众号上去了,再加上之前Google Reader关闭,这让我几乎放弃了之前每天坚持阅读高质量文章的习惯。
之前买了个二手的Kindle4,体验太好了,无论是E-ink屏,还是推送功能,都很舒服,唯一的不足是看扫描版PDF即使切了白边仍然字体过小,如果横屏来看又觉得操作不是很顺手,于是纠结了一阵后,看到有比较便宜的卖全新的DXG的,就趁刚发工资咬牙买了。
昨天早上在taobao拍的,今天下午收到货,然后迫不及待地开箱。没有WIFI就不能免费推送,这是一大遗憾。官方皮套看起来很厚实,装了几本扫描版PDF进去,仍然感觉小了点。官方系统默认不支持中文,书名中带中文的在目录中也不能正确显示,这是点小瑕疵。
忧郁啊,赚的钱远远不够花。这两天遇到瓶颈了,写程序写啥啥不会。想给Ninayan加上链接保存到Readability和发送到Kindle的功能,想想多简单的特性啊,居然遇到很大阻碍。
又好久没写blog了。上上周从推友处入了个二手的Kindle4,这是个很划算的事。350元顺丰到付,成色很新,还有个山寨的皮套。拿到手后,我就爱不释手了。
首先,Kindle4很小很轻,只有6寸,而且没有键盘,一只手就可以竖握整个机器,拿起来很方便,随身携带比带书轻便多了。
其次,E-ink屏真的很赞,真的只有自己实际把玩过,才会体会到它的好。之前很多次都冲动想买个Kindle,都被自己以“我不是个爱看书的人”为理由扼杀了这冲动。这次之前是橙子拿她刚到手的Kindle4来让我玩了一下下,于是就冲动了,刚好推上求二手也便宜,就入了。E-ink的屏幕观感上很接近纸版印刷,让人看起来相比电脑,手机,平板等等觉得更类似书本,另外个好处是,我早上上班路上会拿出来看点东西,如果露天有大太阳的情况下,用Nexus S手机看小说时得把屏幕调到最亮才能看清,E-ink则不在乎这个问题,但同样的,晚上回来如果天黑光线不足,E-ink就不行了,据说可以通过配备小照明灯解决。
再次,Kindle4有很方便的推送功能,只要把指定格式的电子书作为附件发送到Amazon给分配的邮箱里,Kindle在连上WIFI后就会后台自动把书下载来。这样一来,可以实现很不错的功能。比如定时推送RSS等内容,虽然网上已经有一些免费或付费的推送Google Reader或RSS的服务,但我还是打算自己写一个。有几个原因,一是这些服务免费的一般都有比较大限制,比如Google Reader推送时间只能一天一次,顶多一天两次,推送RSS则往往对订阅数有限制。二是我想增加多一些推送的类型,比如小说更新,漫画更新,还有从SNS消息中提取的链接内容。三是推送过来的字体、排版以及插入广告之类,终归不是很舒服。因此要写这样一个程序,打算设计成一个C/S架构的应用,客户端和服务器都具有内容下载生成的功能,但服务器端可以实现定时推送的功能,客户端可以把定时推送的请求发送给服务器端。
最后想说下遗憾的事,6寸屏对于看扫描版16开或22开大小的PDF还是不够理想,我在考虑是不是再入个DXG。
有个同事,平时看我在公司里用手机连公司的WIFI,很是眼热,一直问我怎么用。我就告诉他,要装个ProxyDroid,而且手机得root先。这样持续了将近1个月,今天他突然跑过来对我说,都怪你都怪你,现在我的手机刷得只剩下闹钟了。原来他的HTC G12昨天被他用什么一键root软件强行root,结果不能启动WIFI了。于是今天中午和另一个同事一直在OF外面折腾这手机,希望能恢复WIFI。结果还是没有什么进展,而且最后从网上看到,似乎他的G12是所谓的木马机,笑死了。
今天看到,豆瓣推出阅读器了,除了Web版和iPad版,毫不意外地有Kindle递送服务。说起Kindle,之前有一段时间我非常想买一个电子书,当时只考虑了1000出头的Kindle3和500左右的Bambook,不过好在每当一有这种强烈的购买欲望时,都有一股理性的声音说,你不是个爱看书的人!然后就拖到现在也没有买。自从上次去上海图书馆,亲自把玩了一会儿Bambook,非常庆幸自己没有一时冲动买了这么个设备,这页面切换的速度太慢了,效果太难看了,版式也很丑,啧啧!不知道Kindle到底怎么样,得找个地方也亲身去体验一下,才能决定到底能不能符合我的要求啊。
Tag Windows Phone
之前说过想用Intel C++编译Qt来着,于是从VeryCD上找到Windows、Mac和Linux的Intel C++安装镜象不辞辛苦地下载下来安装。结果让人很沮丧啊。
在Windows 7中,无论编译64位版本还是32位版本,都会编译失败,我怀疑是因为Intel C++用了Visual C++的头文件引起的问题,但是我直接用MSVC2010来编译64位的Qt,虽然也是编译失败,却跟Intel C++报的错误不同,好像C++11标准的问题,在Webkit部分中有类名为nullptr,这个名字在C++11中作为保留字了。也不知道那些用MSVC2010编译成功的是用了什么参数。至于使用MSVC2008的配置,我就没兴趣编译了,因为我不喜欢MSVC2008的SxS。
然后在Mac中编译,32位版本也是编译失败,64位版本编译倒是全部通过了,但貌似make install不完整,那些头文件就没有复制过去,还缺了些什么不知道,反正直接把Qt源代码目录中的include目录复制过去是不能用的。于是也放弃了。
后来么,在Windows上下载了32位和64位的TDM GCC,编译了两个晚上才编译出来,话说那个-nomake "demos examples docs"参数不起作用啊。试了试编译Ninayan 64位,可以运行。
这两天看到Nokia的Qt论坛上有个叫Qt4iOS的人,说他做的Qt for iOS插件就要可以正式发布了,好期待啊。又看到有人说,Necessitas虽然还在Alpha版本,但已经可用性很高了,我看了下,现在居然已经提供4.8.0版本的for Windows/Mac/Linux的SDK了。不过在Mac上安装好后想编译Ninayan才发现,源代码还需要做些修改,比如源代码中通过预定义宏只识别了Windows/Mac/X11/Symbian/Maemon,但是这个Android不知道是什么宏,不知道上哪去查点资料看看。
于是最近还在网上看到的消息,是说Windows Phone的下个版本会支持C++开发,如果这样的话,Qt也会很快就支持WP开发。啊,如果Qt真能用于Android、iOS和Windows Phone的开发,那就太牛逼了。说实话,如果这些port的质量可以的话,只要价格不是太离谱,我应该会买这license去的。
Tag dotNET cpp
前面的blog中,网友sali98提到可以用#pragma init_seg(compiler)等来安排全局对象的构造和析构顺序。这倒是我以前没有想到的,不过经过实际测试后,发现这个方案并不能解决我的问题。
在原来的定位结果中,以为单纯是嵌入的CLR对象晚于C++对象的销毁引起的问题,实际上问题要稍微复杂一点。首先,上次提到的使用_exit引起的对象无声息的消失,不是主要问题。这里调用_exit是在之前有个人把exit换掉的结果,他以为_exit不会调用对象的析构函数,于是不会引起析构时资源销毁时机不正确的问题。事实上这个fix是不起作用的,因为从call stack来看,_exit对嵌入的CLR似乎不起那个作用,而且无论是exit还是_exit都会在对象正常或不正常销毁后仍然有消息循环存在,消息循环中某些处理代码仍然会继续运行,而那些代码也是有可能会引用已消失的singleton的。
最早我想的解决方案是基于这样的想法,既然是C++的singleton在被销毁后没经检验就来使用,那么就把singleton改好一点就行了,我想过《Modern C++ Design》中提到的Phoenix Singleton,也看过一些boost中的Singleton的实现。不过后来都感觉太麻烦,没必要。于是今天试了一个很简单的方法,增加一个static bool变量,标记当前singleton是否有效,然后在每个非static的method开头都先判断一下。简单测试一下,倒是能勉强工作了,不过发现另外一个问题,这样的singleton不止一个!而且另一个不好的地方是,每个非static的method都要修改一下,不必要的改动太多。
今天又看了一下crash的call stack,我就觉得单纯修改singleton的实现似乎不是很高效。于是我就想,是不是有办法在调用exit或_exit前就自己写代码把CLR卸载掉,把消息循环停掉?以我对.NET的粗浅的了解,我觉得嵌入的CLR是应该可以主动卸载掉的,只不过也许某些正在使用的资源会成为阻碍,这个要仔细调研一下。而停掉消息循环这个,感觉也是可以的,增加个标记,在消息循环里判断一下,可以自己主动跳出循环。
Tag KarenMeu
前天傍晚下班回来的路上被追尾了。因为车速比较快,前面的一辆的士突然停下载客,我就急刹车,差点点就要撞上前面的,我都感觉到我的车好像因为刹车踩得太猛而什么东西突然断裂了一样,但是后面另一辆的士就没刹住,撞上我了。看了一下,我只是后面有几条划痕,那的士是右大灯完全废了,都往里陷入了。我也懒得跟他计较,只想着快点回去。
最近几天因为原来做面试的两个同事都到美国培训去了,于是把面试的活都仍给我了。开始还觉得有点新鲜感,两三次后就有点厌倦了,电话面试了好些人,不少还是硕士,不过貌似大多对软件开发并不是很熟练。
接到几个Watson bug,不过实在没经验啊。
KarenMeu迟迟不开工,主要是有两大块还没一个清晰的思路。界面部分想模仿Qt Creator,看了一点源代码,没头绪。另外就是想有一个极度灵活的插件架构,插件主要分两类,一类是界面插件,一类是业务插件,业务插件产生数据,提供给界面显示和操作。同一个业务插件可以让用户自由地选择不同的界面插件进行显示。具体细节想不好该如何实现。
最近过得很开心。
Tag Ainesmile
最近Ainesmile的进展几乎停下来了,因为想到要让它支持像TextMate那样的bundles机制,但又为了避开版权问题而不能直接使用TextMate的bundles,所以就想把那些bundle的格式转换一下用就行了,于是就要写个小程序进行文件格式的转换。为了这个转换小程序更具有通用性和实用性,我就很是贪心地想让它支持在JSON、Apple PList、Windows INI、Java Properties和plain XML任意二者间进行相互转换。本来想想觉得只是个很小的任务,可实际做的时间还是有很多事情要做的,而且想来这样一个具有通用性和实用性的工具应该可以发布给别人使用,于是在包装上也做了更多点的工作,比如画图标,而且为了能在Windows和Mac OS X上都能使用,同时以为以前用过的一个Rapid XML封装更容易使用,结果陷入了无尽的跨平台的fixing中。
昨天发现一个新语言,Rust,据说是Mozilla开发来为了替代C++重写Firefox用的,现在才0.3版本,语言特性也还在快速变化中。看了半天的tutorial,发现语法上给我的感觉是很像Ruby,又有Erlang的一点点元素,而它自称是一种系统编程语言,所以从一开始就很注重与C的交互。它是一种编译型语言,有个叫rustc的编译器,现在还只能通过自己下载编译源代码来使用它。看tutorial的时候突然有个念头,这些年不断冒出来的声称解决了一大堆问题的编程语言,实际上也就是它声称的那些个领域上表现较好而已啊,C语言才是王道啊,哈哈。
在编译Rust的时候,发现它自动下载了最新的LLVM和Clang的源代码并编译好了,于是我就想再试下Mac OS X下用Clang编译下Qt,以前曾经尝试过但失败了。这次也遇到两个错误,就是返回值类型要去const修饰,gitorious上已经有patch的,但在4.8.2上没有合入,自己改一下整个Qt 4.8.2就能用Clang编译通过了。Clang在Mac OS X上基于上处于产品级的质量了,但不知道在Windows上什么时候才能达到近似的水平啊,叹气。貌似Clang对unix-like的系统都支持得挺不错的,甚至能用来编译FreeBSD内核。
最近正在编写一个文本编辑器,取名为Ainesmile。按照惯例,这个名字同样是一个妹汁的id。
这个文本编辑器的目标是成为超越Coda、Sublime Text和TextMate的存在,所以基本的定位是一个代码编辑器,也可以做为一个通用的纯文本编辑器。它使用Qt开发,所以目前可以确认的是它将可以在Windows和Mac上运行,如果移植代价不大,将也会在Linux或FreeBSD等其他Qt支持的桌面环境中运行。
写这么一个文本编辑器的出发点,首先,我觉得Mac OS X上的几个编辑器的功能都很炫目,很有现代感,而Windows平台上除了e,就没有其他类似产品了,而e的功能也似乎只是TextMate的一个子集。其次,我觉得Mac用户真是人傻钱多的存在啊。
功能方面,我觉得实现起来没有特别大的技术难点,只不过工作量有点大。当前一个主要的问题是,美工方面,缺少一套用于菜单、工具栏的图标,以及程序图标。求帮助。
Tag Clang
Clang for Windows早已经可堪实用,官方每隔一个月或几个月会发一个编译好的snapshot外,msys2项目也提供了不是特别新的版本(目前9.0.1)可以直接通过pacman安装使用。作为一个升级控,用上Nightly Build岂不是更爽!当然这不是官方的,而是需要自己下载源代码进行编译。
之前已经在Windows上用clang编译Qt程序,但当时的Qt Creator并没有好好地支持,所以需要在控制台上直接使用命令行进行编译。今天偶然发现最新的Qt Creator已经支持clang-cl套件了,试了一下效果不错。
几年前也曾经试图折腾过Clang on Windows,那时候的完成度还不高,只能配合MinGW使用,而且头文件搜索路径还是源代码中硬编码的。
这两天在Windows下折腾clang。这东东前端是支持C/C++/Objective-C/Objective-C++,后端一般是用LLVM的。在Mac OS X上貌似用得很好,可以生成OSX和iOS的app,貌似在Linux或FreeBSD上也支持得不错的样子,不过在Windows上就纠结了。
首先,clang还是依赖gcc的crt和headers的。于是在Windows上基本上是用MinGW套件的。但是同样是MinGW,不同的人都能编译出不同的东西来,版本众多,质量也不同,貌似还是MinGW官方编译的版本最为稳定,MinGW-w64的x64版本貌似就压根编译不了clang。
众多32位版本的MinGW都可以编译clang,但是,编译出来的clang貌似就是能自举了,真是遗憾,也不知道是不是我哪里弄错了,4.4.0版本是报BFD模块中有个内部错误,4.6.3版本是在链接时报错,4.7.x版本则是编译第一个文件就报命令行参数错误。
我是在msys中编译的,值得提一下的是,它每次都要做rebuild all才行,incremental build貌似是不行的。还有就是perl中的pod2html.bat在msys中是用不了的,所以在make install时都会报错的。
最后要注意,编译clang前,需要修改下llvm\tools\clang\lib\Frontend\InitHeaderSearch.cpp中MinGW的头文件搜索路径。最简单的办法是硬编码增加搜索路径,但是这样你的MinGW和clang就只能存放在固定的位置了。我看了一下clang dev去年4月的maillist中一个thread,其他他们就是没找到一个高效低成本的方案来解决这个问题。于是我就自己用了一种quick & dirty的方案。先查找clang所在目录是否有gcc.exe,没有就找PATH环境变量中有没有,再没有就试试各个分区根目录下有没有mingw目录,如果能找到gcc.exe,就运行gcc.exe -v命令,得到target和version,这样就可能得到搜索路径了。自己写了大约200行代码,粘贴到这里了。
最近Ainesmile的进展几乎停下来了,因为想到要让它支持像TextMate那样的bundles机制,但又为了避开版权问题而不能直接使用TextMate的bundles,所以就想把那些bundle的格式转换一下用就行了,于是就要写个小程序进行文件格式的转换。为了这个转换小程序更具有通用性和实用性,我就很是贪心地想让它支持在JSON、Apple PList、Windows INI、Java Properties和plain XML任意二者间进行相互转换。本来想想觉得只是个很小的任务,可实际做的时间还是有很多事情要做的,而且想来这样一个具有通用性和实用性的工具应该可以发布给别人使用,于是在包装上也做了更多点的工作,比如画图标,而且为了能在Windows和Mac OS X上都能使用,同时以为以前用过的一个Rapid XML封装更容易使用,结果陷入了无尽的跨平台的fixing中。
昨天发现一个新语言,Rust,据说是Mozilla开发来为了替代C++重写Firefox用的,现在才0.3版本,语言特性也还在快速变化中。看了半天的tutorial,发现语法上给我的感觉是很像Ruby,又有Erlang的一点点元素,而它自称是一种系统编程语言,所以从一开始就很注重与C的交互。它是一种编译型语言,有个叫rustc的编译器,现在还只能通过自己下载编译源代码来使用它。看tutorial的时候突然有个念头,这些年不断冒出来的声称解决了一大堆问题的编程语言,实际上也就是它声称的那些个领域上表现较好而已啊,C语言才是王道啊,哈哈。
在编译Rust的时候,发现它自动下载了最新的LLVM和Clang的源代码并编译好了,于是我就想再试下Mac OS X下用Clang编译下Qt,以前曾经尝试过但失败了。这次也遇到两个错误,就是返回值类型要去const修饰,gitorious上已经有patch的,但在4.8.2上没有合入,自己改一下整个Qt 4.8.2就能用Clang编译通过了。Clang在Mac OS X上基于上处于产品级的质量了,但不知道在Windows上什么时候才能达到近似的水平啊,叹气。貌似Clang对unix-like的系统都支持得挺不错的,甚至能用来编译FreeBSD内核。
Tag Rust
自从Rust版本号跳到1.0,即使离正式发布还有很长一段时间,我就开始打算要学一下Rust,主要还是因为想跟Go比较一下,用Go也一年了,已经能做些比较实用的小项目了,我想看看Rust有哪些方面更优秀,或者说比Go更合适来做某些方面的开发。
Rust总用来跟C++,尤其是Go来对比。我也差不多学了并用了近一年的Go,基本上可以用来独自做些并不复杂的程序,最近特别想去学一下Rust,想看看到底和Go各有什么优缺点。
最近Ainesmile的进展几乎停下来了,因为想到要让它支持像TextMate那样的bundles机制,但又为了避开版权问题而不能直接使用TextMate的bundles,所以就想把那些bundle的格式转换一下用就行了,于是就要写个小程序进行文件格式的转换。为了这个转换小程序更具有通用性和实用性,我就很是贪心地想让它支持在JSON、Apple PList、Windows INI、Java Properties和plain XML任意二者间进行相互转换。本来想想觉得只是个很小的任务,可实际做的时间还是有很多事情要做的,而且想来这样一个具有通用性和实用性的工具应该可以发布给别人使用,于是在包装上也做了更多点的工作,比如画图标,而且为了能在Windows和Mac OS X上都能使用,同时以为以前用过的一个Rapid XML封装更容易使用,结果陷入了无尽的跨平台的fixing中。
昨天发现一个新语言,Rust,据说是Mozilla开发来为了替代C++重写Firefox用的,现在才0.3版本,语言特性也还在快速变化中。看了半天的tutorial,发现语法上给我的感觉是很像Ruby,又有Erlang的一点点元素,而它自称是一种系统编程语言,所以从一开始就很注重与C的交互。它是一种编译型语言,有个叫rustc的编译器,现在还只能通过自己下载编译源代码来使用它。看tutorial的时候突然有个念头,这些年不断冒出来的声称解决了一大堆问题的编程语言,实际上也就是它声称的那些个领域上表现较好而已啊,C语言才是王道啊,哈哈。
在编译Rust的时候,发现它自动下载了最新的LLVM和Clang的源代码并编译好了,于是我就想再试下Mac OS X下用Clang编译下Qt,以前曾经尝试过但失败了。这次也遇到两个错误,就是返回值类型要去const修饰,gitorious上已经有patch的,但在4.8.2上没有合入,自己改一下整个Qt 4.8.2就能用Clang编译通过了。Clang在Mac OS X上基于上处于产品级的质量了,但不知道在Windows上什么时候才能达到近似的水平啊,叹气。貌似Clang对unix-like的系统都支持得挺不错的,甚至能用来编译FreeBSD内核。
Tag Linux
之前一段时间一直遇到一个问题,假设有L和R两个程序,L负责启动R,杀掉R,或者在R异常退出时自动重启R,众所周知在Linux上一个程序要运行另一个程序,是先fork,然后exec执行另一个程序代码。于是问题来了,大绝大多数情况下L和R都如预期地运行,但有时候会出现R没被运行起来,用ps看是两个L在跑,也就是说fork了之后没执行到exec那儿!
买硬盘有一段时间了,当时的想法是可能要做Linux平台的开发,所有自己家里的机器上也得正儿八经地装个Linux某个发行版,于是纠结了很久,终于在京东上花了总共780块大洋买了个WD的绿盘2T。结果把硬盘装入机器后,只是分了十几个分区,就再也没动静了。
后来过了大概2、3周吧,实在对自己鄙视得受不了了,翻出两个8G的U盘来,一个是花了20块大洋从淘宝买的,谁料想过了没多久公司(已经是前公司了)又因为十周年纪念每人发了一个8G的U盘。于是从网上找资料看了一下,在Windows系统下用一个叫Win32Image Writer的程序把Linux发行版的ISO镜像写到U盘里,就可以从U盘启动安装了。
先是装了个Debian 6,用的GNOME,装好后发现屏幕闪得厉害,估摸着是显卡驱动的问题,据说ATI的显卡Linux就是支持不怎么好,我的是Radeon HD 4540,从网上找了一圈各种解决方案,试了各种配置和开源闭源驱动,都没效果,很失落。本来对Debian的印象很好的,就是一种运行速度快,而且稳定的发行版,因为曾经在公司用VirtualBox装了LinuxMint和Debian同时编译clang,发现在Debian下要快不少。可是现在的闪屏问题使得这个系统处于基本不可用的状态。后来我还试了换GNOME为KDE,果然没用。于是知彻底绝望了。
因为Debian的闪屏问题搞不定,于是只好试着装装Ubuntu12.04这种小白发行版,它果然一装上就所有驱动都搞定了,不光是我那块显卡,连在10.04时需要自己找相同芯片其他牌子无线网卡的驱动源代码来自己编译安装才能使用的Fast无线网卡都直接驱动了。真是让人感叹果然是个适合我等小白使用的发行版。本以为问题就这样搞定了,于是下载了qt呀,qt creator呀,clang呀之类的源代码,都编译了使用。可是好景不长,不到两个星期,就出现各种问题。比如启动特别慢,在红黑屏要停留很久,一开始都以为是启动不了了,后来才发现是因为需要时间很长。再后来,各种已有的分区不能自动挂载了。虽然可以自己敲命令挂载,但终归让人心里极其不爽。到现在,居然不能关机了,一直停在关机logo界面里了。失望透顶,Ubuntu是从7.x以来,各个版本都装过的,窃以为最不稳定的Linux发行版,没有之一。
今天实在对Debian和Ubuntu失望之极,打算再换个发行版试试。之前在VirtualBox中用过不短时间的Arch,Fedora,openSUSE和Mandriva,对于Arch和Gentoo,我就担心显卡问题搞不定。对于后三者,不是很喜欢它们的包管理机制。于是最后打算看看Mint吧。以前在VirtualBox中也装过Mint,现在公司里还装着用呢,它默认不使用GNOME或KDE,而是使用Mate或Cinnamon,感觉挺精致的。在装Mint还是LMDE之间犹豫了一会儿,后来看LMDE用的是Debian的testing源,在我看来相当于放弃了Debian的稳定性这一大优势,所以还是用Mint吧。安装过程仍然一样,写入U盘可以当Live盘启动,然后安装,很快很傻瓜。而且我之前装Debian和Ubuntu把它们的/home都放到同一个分区,而且两个系统中都用相同的用户名,在Mint中也这样做,就可以直接使用以前做好的一些把配置写到/home目录的软件的配置了。
Mint用了近一天了,感觉不错,就看它能用多久吧。
Tag iPad Mini
iPad Mini和Surface都快要发布了,各种消息满天飞,我最关心的当然是价格了,因为作为当今世界上做软件系统最好的两家公司,他们的产品足够吸引我的注意力!
不过iPad Mini最低配的价格貌似还可以接受,Surface的就远远超出我的预期了。叹气啊!但是很可能过段时间仍然咬咬牙上了,再托阿菲帮忙从美国带吧,估计Surface至少比国内买行货少花费500人民币吧。
Tag Surface
iPad Mini和Surface都快要发布了,各种消息满天飞,我最关心的当然是价格了,因为作为当今世界上做软件系统最好的两家公司,他们的产品足够吸引我的注意力!
不过iPad Mini最低配的价格貌似还可以接受,Surface的就远远超出我的预期了。叹气啊!但是很可能过段时间仍然咬咬牙上了,再托阿菲帮忙从美国带吧,估计Surface至少比国内买行货少花费500人民币吧。
Tag Google Reader
最近有很认真地在写一个Google Reader客户端,仍然是使用的Qt,一切为了跨平台嘛。之前Ninayan用QML写的UI,虽然能做出一些比较炫的效果,但没有一个优秀的美工,再炫的效果最后得到的都是不好的用户体验。于是这次使用了传统Widget来做UI,感觉还不错,中规中矩的,源代码也放在github上了。
到现在为止,Google Reader的客户端功能基本上实现了,可能还有些小细节需要修改。前两天因为工作上的关系,找了点资料在看怎么提高socket的效率,公司那个产品全部是用的select模型,貌似Qt的QNetworkAccessManager类也是用的select,这个东西的好处在于大多数的系统都直接支持,思路也简单,但是对于追求高吞吐率的情况下,就得用各个系统内核各有的一套东西了,比如Windows下得用完成端口,Linux下,2.6以后版本的内核得用epoll/AIO,BSD/Mac下又有kqueue等等,可谓是八仙过海各有神通啊。然后我就又找到了asio,这个库以前用过Boost里的那个版本,没用好,当时的感觉是资料太少了,性能太差了,后来也都是尽量避开自己写socket相关的代码,直到后来用Qt中的QNetworkAccessManager。这两天抑制不住地想把QNetworkAccessManager改成用asio实现,以达到各平台优化的尽量大吞吐率。忍住!
基本功能完成后,我就开始想着把程序改成插件架构,以插件的形式支持从不同的源获取信息,比如Twitter,Facebook,国内的微博等等,也以插件的形式支持把当前内容分享到不同的宿。其实从功能上来说,跟Ninayan是有很大重叠的,毕竟当时写Ninayan也是为了做一个信息获取工具,只不过从UI的设计上限制了操作方式,最终在用户体验上会有很大的差别。
Tag SANSASORI
最近有很认真地在写一个Google Reader客户端,仍然是使用的Qt,一切为了跨平台嘛。之前Ninayan用QML写的UI,虽然能做出一些比较炫的效果,但没有一个优秀的美工,再炫的效果最后得到的都是不好的用户体验。于是这次使用了传统Widget来做UI,感觉还不错,中规中矩的,源代码也放在github上了。
到现在为止,Google Reader的客户端功能基本上实现了,可能还有些小细节需要修改。前两天因为工作上的关系,找了点资料在看怎么提高socket的效率,公司那个产品全部是用的select模型,貌似Qt的QNetworkAccessManager类也是用的select,这个东西的好处在于大多数的系统都直接支持,思路也简单,但是对于追求高吞吐率的情况下,就得用各个系统内核各有的一套东西了,比如Windows下得用完成端口,Linux下,2.6以后版本的内核得用epoll/AIO,BSD/Mac下又有kqueue等等,可谓是八仙过海各有神通啊。然后我就又找到了asio,这个库以前用过Boost里的那个版本,没用好,当时的感觉是资料太少了,性能太差了,后来也都是尽量避开自己写socket相关的代码,直到后来用Qt中的QNetworkAccessManager。这两天抑制不住地想把QNetworkAccessManager改成用asio实现,以达到各平台优化的尽量大吞吐率。忍住!
基本功能完成后,我就开始想着把程序改成插件架构,以插件的形式支持从不同的源获取信息,比如Twitter,Facebook,国内的微博等等,也以插件的形式支持把当前内容分享到不同的宿。其实从功能上来说,跟Ninayan是有很大重叠的,毕竟当时写Ninayan也是为了做一个信息获取工具,只不过从UI的设计上限制了操作方式,最终在用户体验上会有很大的差别。
Tag blog
今天发现自己的blog实在太慢了,偶然的机会知道了AppDynamics这个服务,注册了个账号可以免费试用15天,然后就给blog加上试了下,发现blog慢得让人发疯,我前些天把家里的线路优化,海外IP全部走IPLC,今天看来blog打开仍然很慢,更别提其他家里网络没我好的人了,我觉得没法忍,必须改。
去年把blog托管到了coding pages上,以为可以为大陆提供更好的访问速度,但实际上效果似乎并没有想像的那么好,coding pages貌似是为了规避大陆网页要求备案,把大陆访问IP引导到了香港的主机上,网络一旦出了国,速度就会降很多,另一点是免费的coding pages要求在页面上添加他们的声明信息,虽然就算他们不要求,我也会在页脚处添加各种感谢声明,但强行要求就让我心里总有点疙瘩。
自从重新开始写blog,都是托管在github pages上,然后通过cloudflare中转以及https证书。这一套方案总的说来工作得挺好的,但是,万事就怕但是,在大陆cloudflare的服务并不是特别稳定。后来发现Coding.net也提供Pages服务了,还集成了Let’s Encrypt的证书服务,于是就迁过去了。
上周在cloudflare又新建了个账号,记得很多年前我有个账号的,不过忘了密码也忘了注册邮箱,只好再新建个。然后用free plan加了两个域名,其中一个就是现在blog在用的minidump.info,cloudflare除了CDN,还能提供SSL,这点非常赞,于是就加上了。昨天晚上看到有人说自己在github pages上的blog因为敏感词被GFW过滤而reset了某个页面,于是我想不如把整站强制使用https算了。说干就干,因为我用的是Jekyll,只要在_layout的模板中加几行Javascript代码就可以搞定:
最近在写一个彩票辅助分析程序,觉得研究彩票是个比较有意思的事情,在网上看了很多有根据没根据的文字,想把其中的一部分用程序实现出来,也不知道有没有道理,所以同时想把这些事情记录下来。
Tag wordpress
自从知道nginx后,就再也不愿意用Apache了,总觉得Apache配置复杂、体积笨重、运行缓慢,当然这些只是我的无根据臆想。原本用nginx只是用来做静态站,做反向代理,今天zhangh说想要个Wordpress做产品展示页面,于是只好弄一下。顺便感叹一下他的执行力。
最近在写一个彩票辅助分析程序,觉得研究彩票是个比较有意思的事情,在网上看了很多有根据没根据的文字,想把其中的一部分用程序实现出来,也不知道有没有道理,所以同时想把这些事情记录下来。
Tag jekyll
自从给blog换了个theme,一直断断续续在调整一些细节,于是不免要用到jekyll,不过前些天手贱给公司的iMac升级所有gems,结果升坏啦,一运行jekyll serve就会报错:
上周在cloudflare又新建了个账号,记得很多年前我有个账号的,不过忘了密码也忘了注册邮箱,只好再新建个。然后用free plan加了两个域名,其中一个就是现在blog在用的minidump.info,cloudflare除了CDN,还能提供SSL,这点非常赞,于是就加上了。昨天晚上看到有人说自己在github pages上的blog因为敏感词被GFW过滤而reset了某个页面,于是我想不如把整站强制使用https算了。说干就干,因为我用的是Jekyll,只要在_layout的模板中加几行Javascript代码就可以搞定:
最近在写一个彩票辅助分析程序,觉得研究彩票是个比较有意思的事情,在网上看了很多有根据没根据的文字,想把其中的一部分用程序实现出来,也不知道有没有道理,所以同时想把这些事情记录下来。
Tag github
最近在写一个彩票辅助分析程序,觉得研究彩票是个比较有意思的事情,在网上看了很多有根据没根据的文字,想把其中的一部分用程序实现出来,也不知道有没有道理,所以同时想把这些事情记录下来。
Tag coding
因为程序使用了多进程的架构,有时候需要在子进程被启动后非常早的阶段就进行调试,比较常见的极端情况是要调试子进程的main()函数,MSVS上有插件可以在同一个调试环境同时挂载父进程和子进程进行调试,WinDBG在启动被调试程序时自带选项支持同时调试父子进程,但就我使用下来的体验发现,这时调试器的性能会变得非常差,非常影响心情和调试效果。也有比较low的办法,就是在子进程的main()函数开头加一个MessageBox,使其启动后用户有机会使用调试器attach子进程进行调试,但要改代码终归麻烦了点,而且不是所有程序都适合加MessageBox。
最近这段时间写了个债权匹配管理系统,然后交给同学公司的人去用了,结果各种小问题都暴露出来了。比如因为服务器上默认时区设置的不同,导致从数据库里取出来的时间字符串格式有些微变化,而客户端在解析这字符串时的逻辑写得太死了,于是挂了。比如double类型与字符串类型互转,在数值比较小的时候没问题,数值较大时就用科学记数法表示了,于是转不下去了。
今天终于把Thumbnail Service的性能问题解决了。
以前吧,虽然经常被骂,还被气得肝疼,但那都是人际方面的问题,还可以安慰自己至少做的事情还是比较有兴趣的。现在嘛,被骂得少了很多,倒是做的事情越来越没意思了。
最近一直在用shell脚本自动在跑一个简单的测试,就是不停地停止和重新启动一个relay进程,如此反复轮循,这样每过一段时间,比如两三天,或者更短或者更长,就会遇到一个问题:再也停不了任何一个relay进程,也不会重新启动进程。
之前提到过在公司的一个项目里用了websocket,client侧用C++开发,选了libwebsockets,使用的过程中遇到一些问题,这一个星期都是在不停地解决各个问题,好在现在终于基本上都搞定了,现在记录下来。
Relay在线上时不时报些bug,不但客户和公司的人怨言颇多,我也苦不堪言。每次出现问题的时候,美国的PM都会在邮件里说Relay是个very important的东西,万万不能出问题,可是我怎么没看出公司对Relay有very important的重视和投入呢!整个项目除了web前端页面,其他的几乎是我一个人在开发和维护,而且我全职投入也就不到一年时间,后面就重心放在其他项目了,特性仍然在加,bug仍然要改,投入时间却是越来越少,直到现在每个月都不能保证有一二十个人时在上面。前些天一个QA说Relay的bug最多了,这时另一个开发帮忙说是因为投入时间太少。虽然说的是实话,但仍让我感到很惊讶,总算还有人知道实情。可是那些PM,Director之类的却不知是真不了解情况还是故意视而不见。
之前说过,我把一个项目中的程序线程数都尽量减少了,差不多就是一个程序用一个线程来跑一个event loop来服务所有socket,结果这几天发现似乎性能有点跟不上了。
之前注册了搜狐云景PaaS,被送了100元的券,不过当时看了一下发现不支付Go程序,于是就没玩下去了。前几天连续收到几封邮件,说钱要花完了,也没放在心上,觉得反正玩不了,就随它去吧。今天在v2ex上看到有人说可以免费送3个月的使用配额,于是又上后台看了一下,发现它居然使用限制那么少,可以自己在配置文件中指定要运行的程序路径,这样就可以部署Go程序了,立马把之前在京东云上部署的ifconfig在搜狐云景上也部署了一个,感觉还不错。
前面提到过,因为了读了一点《Linux多线程服务端编程》,觉得自己对网络编程有了更多的了解,可以对公司里负责开发维护的那个小项目动手重构了。这个小项目从功能上简单说来,就是个流量转发器,也可说成是个中断器,所以项目名称就叫Relay了。几乎每个刚听到这句话的人,都会第一时间发出疑问:这种功能网上开源代码或现成工具应该有很多,比如nginx就有类似的功能,为什么要自己做一个?答案可以从两个方面来回复,一种霸道无理点的说法是,这是公司策略,这个理由足以堵住所有质疑者的嘴巴。另一种理性点的说法是,自己做可控性好,可扩展性也好,比如我们要有实时的流量统计,我们要自定义高效的传输协议,像nginx的http传输性能不能完全满足我们的需求等等。
Yiili论坛程序是从wetalk改过来的,所以是用了beego这个Web Framework的。前两天Beego从1.2.0升级到1.3.0,有一个用到的接口被删了,用另一个新增的接口替代,于是Yiili就编译不过了。其实据说这个被删掉的接口已经有3,4个版本标记为deprecated了,只是我才接触beego差不多1个月,所以肯定不会知道这回事的,于是即使自己照猫画虎地尝试修改,即使能编译通过了,运行也仍然不正常。Beego的官方论坛上也有人在喊这个问题,一直到第二天,Beego的作者astaxie大概实在受不了人的呱噪,直接把wetalk的不兼容代码给改了。这次事件给我的感觉非常不好,还跑到Go的中文邮件列表去问遇到这种第三方库接口变化引起不兼容的问题该怎么解决。结果有人说,官方的做法是把第三方库在自己的代码库里copy一份,唔,这是我最不喜欢的做法,像svn external,git submodule不都是为了避免这种做法吗!但是go get不支持版本,所以是没办法做到的。还有人提出个我觉得还能接受的办法,在GOPATH里加3个路径,第一个专门放go get取下来的第三方库,里面的东西随时可以删掉,第二个专门放被自己修改过或认为是stable的第三方库,可以保证自己的项目能编译通过的,第三个专门放自己的项目代码。
前几日在重构一个小模块。这个模块的架构本来就很畸形,因为它被要求在不同的设备不同的平台不同的endpoint上运行不同的逻辑,却要做在一个模块里,能给用户一个.a或.lib就可以使用。于是第一版的实现中就有一个变量来区分当前endpoint是哪个,开始还好,后来越来越多的if条件判断endpoint来运行不同的逻辑,代码就丑到令我觉得恶心。于是我就蠢蠢欲动了好久,最后看重构的工作量也不是很大,就跟design这块的小leader打了个招呼开始重构了。
忘了从何时起,就不太乐意写blog了,一直在长草。前两天从知乎网友Jim处扒来一个非常简洁明快的Jekyll theme,于是打算写点文字除除草。
花了几天时间,把原本基于XML的IPC重要部分都改成用Protobuf了,之前以为会大幅度提高运行效率,结果发现原本用RapidXML库生成消息,比填充Protobuf结构慢不了多少。不过可以肯定的是,消息长度缩短为差不多是原来的1/4了,原本16KB左右,之后4KB多点。
今天早上csdn的人打电话来催了,让我快点提交应用,我说我已经写了一半了。其实不然,我只能说只搭了个框架,所有核心的内容都没开始动手呢。这次又是被block住了,又是因为不能为这个业务设计一个合适的数据结构而进行不下去了。总的说来简单的数据结构在学校时学过一点,然后就一直啃老到现在,但一直缺少能根据具体业务逻辑而举一反三地设计合理的数据结构的能力。真是忧伤啊!
Tag software
这几天突然又想试试C++ Builder,现在最新的版本是12.1。曾在大学时使用C++ Builder 6写过一些小程序,这么多年过去,源代码丢掉了一些,还能找到一些。用12.1是不能直接打开6.0的工程文件的,需要新建VCL工程,再把窗体文件、源代码文件和头文件添加进去,才能编译。12.1的VCL整体上变化不大,主要是字符串类变成了UnicodeString,以前的C++ Builder和Delphi在字符编码方面的支持确实是一大弱项,项目代码拷过来后,主要就是字符串部分需要修改一下。
今天早上csdn的人打电话来催了,让我快点提交应用,我说我已经写了一半了。其实不然,我只能说只搭了个框架,所有核心的内容都没开始动手呢。这次又是被block住了,又是因为不能为这个业务设计一个合适的数据结构而进行不下去了。总的说来简单的数据结构在学校时学过一点,然后就一直啃老到现在,但一直缺少能根据具体业务逻辑而举一反三地设计合理的数据结构的能力。真是忧伤啊!
Tag shareware
这两天看论坛,又想到两个对我来说比较有用的东西。其中一个是密码管理。
今天早上csdn的人打电话来催了,让我快点提交应用,我说我已经写了一半了。其实不然,我只能说只搭了个框架,所有核心的内容都没开始动手呢。这次又是被block住了,又是因为不能为这个业务设计一个合适的数据结构而进行不下去了。总的说来简单的数据结构在学校时学过一点,然后就一直啃老到现在,但一直缺少能根据具体业务逻辑而举一反三地设计合理的数据结构的能力。真是忧伤啊!
Tag qterminal
发现FreeBSD上的LXterminal很容易在输入长命令时换行错位,于是胡乱覆盖掉前面的内容,就很难好好地输入完一整条长命令。这事在Debian上没遇到过,我也只在Debian上装过LXDE并使用LXTerminal。其他在Linux上用过的Terminal也只有GNOME Terminal和Mate Terminal,感觉吧每种Terminal都是配合自家的DE的,虽然可以混用但心里总是有点疙瘩。
Tag LXTerminal
发现FreeBSD上的LXterminal很容易在输入长命令时换行错位,于是胡乱覆盖掉前面的内容,就很难好好地输入完一整条长命令。这事在Debian上没遇到过,我也只在Debian上装过LXDE并使用LXTerminal。其他在Linux上用过的Terminal也只有GNOME Terminal和Mate Terminal,感觉吧每种Terminal都是配合自家的DE的,虽然可以混用但心里总是有点疙瘩。
Tag Internet
最近又被结结实实体验了一把国内的恶劣的网络环境。两件事情,一件还是说之前那位同事要搞个社区,域名备案的问题,用了阿里云的主机,然后说已经准备齐全了各种材料去备案,已经快递到了河南省内某处,过了大概快3个星期了,前几天他跟我说收到那边的消息,说还需要大概20个工作日才可能会给他进一步的是否备案通过的消息。我表示只能呵呵了,这么搞真的有意义么有意义么有意义么?
Tag Yiili
Yiili和MiaoCoffee是基于同一个codebase,目前的区别主要在描述性文字等周边部分。现在Yiili和MiaoCoffee都算正式上线了,之后的工作重心就在运营上了。MiaoCoffee的运营我肯定基本上是不管的,那个其实不算我自己的项目,我的主要精力将放在Yiili上,Yiili上我才有绝对的控制力和话语权。总的说来,我也只是因为有Yiili才会顺便花点时间给MiaoCoffee做些技术支持工作。我在人脉方面几乎没有任何基础,所以很难直接拉些人来活跃气氛。于是我想着前期只能自己生产些内容来吸引流量了,而内容生产是件不容易的事,对我来说有两条路可以走,一是找那些还算有交情并且交情还不错的又在某方面的知识掌握得比较多的朋友,请他们偶尔抽空写点两三百字的超短篇,再配张图就算是图文并茂了,二是从国外找内容自己翻译。前者产量极不稳定,后者产量要稳定得多但要占用大量时间。除了通过生产内容吸引流量外,另外我想到的一个也许效果并不怎样的办法是同步SNS,比如微博,微信等等。等项目起步后,就可以开始考虑推出移动app了,这样既能显示专业和认真,又能降低使用门槛和提高用户体验。大体思路就是学v2ex那样通过技术手段来弥补一些资源上的不足。
Tag MiaoCoffee
Yiili和MiaoCoffee是基于同一个codebase,目前的区别主要在描述性文字等周边部分。现在Yiili和MiaoCoffee都算正式上线了,之后的工作重心就在运营上了。MiaoCoffee的运营我肯定基本上是不管的,那个其实不算我自己的项目,我的主要精力将放在Yiili上,Yiili上我才有绝对的控制力和话语权。总的说来,我也只是因为有Yiili才会顺便花点时间给MiaoCoffee做些技术支持工作。我在人脉方面几乎没有任何基础,所以很难直接拉些人来活跃气氛。于是我想着前期只能自己生产些内容来吸引流量了,而内容生产是件不容易的事,对我来说有两条路可以走,一是找那些还算有交情并且交情还不错的又在某方面的知识掌握得比较多的朋友,请他们偶尔抽空写点两三百字的超短篇,再配张图就算是图文并茂了,二是从国外找内容自己翻译。前者产量极不稳定,后者产量要稳定得多但要占用大量时间。除了通过生产内容吸引流量外,另外我想到的一个也许效果并不怎样的办法是同步SNS,比如微博,微信等等。等项目起步后,就可以开始考虑推出移动app了,这样既能显示专业和认真,又能降低使用门槛和提高用户体验。大体思路就是学v2ex那样通过技术手段来弥补一些资源上的不足。
Tag Restaurant
Yiili和MiaoCoffee是基于同一个codebase,目前的区别主要在描述性文字等周边部分。现在Yiili和MiaoCoffee都算正式上线了,之后的工作重心就在运营上了。MiaoCoffee的运营我肯定基本上是不管的,那个其实不算我自己的项目,我的主要精力将放在Yiili上,Yiili上我才有绝对的控制力和话语权。总的说来,我也只是因为有Yiili才会顺便花点时间给MiaoCoffee做些技术支持工作。我在人脉方面几乎没有任何基础,所以很难直接拉些人来活跃气氛。于是我想着前期只能自己生产些内容来吸引流量了,而内容生产是件不容易的事,对我来说有两条路可以走,一是找那些还算有交情并且交情还不错的又在某方面的知识掌握得比较多的朋友,请他们偶尔抽空写点两三百字的超短篇,再配张图就算是图文并茂了,二是从国外找内容自己翻译。前者产量极不稳定,后者产量要稳定得多但要占用大量时间。除了通过生产内容吸引流量外,另外我想到的一个也许效果并不怎样的办法是同步SNS,比如微博,微信等等。等项目起步后,就可以开始考虑推出移动app了,这样既能显示专业和认真,又能降低使用门槛和提高用户体验。大体思路就是学v2ex那样通过技术手段来弥补一些资源上的不足。
Tag film
周日去电影院看了《沉睡魔咒》。本来打算周六去的,结果相当不愉快的一次网上订票,先去大众点评网上买了两张团购券,还以为每张可以便宜7元钱,结果到嗨电影网上订票还要再付12元,也就是说每张票才便宜了1元钱,还花了一些时间折腾微信支付什么的,我只能说这两家网站的用户体验做得很烂。而且当时没订票成功,我又看手机上收到了两条短信以为已经订票成功了,其实是大众点评网发来的,于是兴冲冲跑去电影院,然后妹子发脾气了,关在卧室里整整一个下午。叹气。
Tag nginx
之前就发现了,Linode是默认带一个IPv6地址的,最近公司里的项目要做一点跟IPv6相关的工作,我就想多了解点IPv6相关的东西,于是想到把我的web站点支持IPv6。
自从知道nginx后,就再也不愿意用Apache了,总觉得Apache配置复杂、体积笨重、运行缓慢,当然这些只是我的无根据臆想。原本用nginx只是用来做静态站,做反向代理,今天zhangh说想要个Wordpress做产品展示页面,于是只好弄一下。顺便感叹一下他的执行力。
Tag Go
本来由于使用网关的方式进行科学上网一直工作得比较稳定,所以很久都没折腾科学上网相关的东西了。前不久用了几年的Banana Pi突然连不上了,通过socks5+pac的方式也勉强应付了。今天回到老婆娘家,发现两个月前还工作得好好的树莓派不知道什么时候已经点不亮了。不禁感叹ARM板似乎不太耐操啊,以后还是尽量只用x86的工控机之类的吧。
前段时间开了一个微信公众号《软件开发谈》,可以通过搜索ID“softwaredevtalk”找到,也可以通过扫描文末二维码找到,主要发些与我本职工作相关的Go、C++、软件工程方面的文章。到目前为止发了十几篇文章都是罗列了些modern C++的新特性:
用C++写程序时,有些事情发现用Go做很容易,用C++则比较折腾,所以就想用Go实现,然后通过cgo链接到C++程序中。但是cgo在Windows上只能使用gcc实现,有时我又有必须使用MSVC的理由。
过去一周仍然花了些时间更新微信公众号爬虫,又踩到些坑,记录一下。
不知道怎么想的,突然开了个新坑,因为bilibili mac client并不能好好地工作,所以自己写一个也挺好玩的。
没心情给avege做新功能,就断断续续做些重构工作,用gocyclo看出来很多函数的圈复杂度都很高,常规的做法,除了把一个大函数拆成几个小函数外,还要对代码逻辑进行调整,比较可观的做法是把if-else,switch-case和select-case替换掉。
Avege开源后并没有太大的变化,除了收获了180多个star,大概也没什么人真正用上,别说PR了,连issue都没有,不过也收集了一些意见和建议。
昨天把Avege客户端部分的源代码单独取出来,放到github上了。然后在v2ex上发了个帖,在twitter上发了条推,在Telegram上的一些群里发了条消息。终于有了一个star数过100的repo了:P
经过大半个月的折腾,兼容SSR混淆和协议的坑终于填上了,目前混淆支持plain、http_simple、http_post、random_head、tls1.2_ticket_auth几种,协议支持origin、verify_sha1即原版SS的One Time Auth、auth_sha1_v4、auth_aes128_md5、auth_aes128_sha1几种。
之前写好的tls1.2_ticket_auth在接收到大量数据时会decode出错,后来发现auth_sha1_v4在接收大量数据时最后一块数据时会要等一段时间才能收到。由于tls1.2_ticket_auth的问题在前面那么多天的仔细排查定位后,仍然毫无头绪,我觉得auth_sha1_v4的问题应该会容易一些,就先尝试一下修正这个问题。
代码几天前就写完了,就是调试不通,昨天晚上偶然在github上看到从libev版分离出来的obfsplugin,都打算用CGO集成到avege去算了,今天上午甚至把编译、链接错误全都改完了,后来想想CGO还是不太好。
本来实现了tls1.2_ticket_auth混淆方法后,我觉得够用了,便想直接去做auth_sha1_v4协议了,但是调试了两天,没调通,很沮丧,还觉得没什么头绪。至少在调试混淆方法时,我用C#版做对比,通过抓包可以明确比较我的程序混淆结果是否正确,但协议就要麻烦些,协议是将加密前的数据预处理一遍,很难对比我的程序是否处理正确了。
虽然Go实现的代码是照着C#版的代码翻译过来了,但是引入了很多问题,经过几天的仔细排查,现在tls1.2_ticket_auth混淆功能终于完成了!稍微记录一点需要注意的点,以便日后翻阅。
这几天断断续续地移植着SSR的一个混淆插件tls1.2_ticket_auth,至今仍然没能正常工作起来,忧郁啊。稍微记录一点读ss-go和ssr-csharp/ssr-libev的代码所得,以便日后翻阅。
Avege最早的目标是成为一个redsocks的另一个实现,用Go做方便地跨平台,同时相比redsocks原版要多增加shadowsocks协议的支持。可是后来却只实现了shadowsocks协议,就只顾着做其他功能去了。
从妹子家里拿回来的树莓派1B不知道出了什么问题,开机只能跑个一两天,之后就连不上网了,从路由器看它也掉线了,只能断电重启才能再次连上。连续遇到两次,我也没耐心继续耗下去了,打算重装系统,原本用着Raspbian,1B的机能实在差了点,于是想着装Archlinux这种比较轻量级的试试,另外一个想用Archlinux的原因是它的官方仓库里一般会有比较新的GccGo安装包,avege用Go开发,试试GccGo编译是否会有更好的性能表现。
之前也折腾过,但是没完美解决,最近在爬些数据,然后想保存成统一的编码,于是自然而然地有编码转换的问题,在网上找最多的解决方案是通过CGO调用iconv实现,这个方案在mac或Linux之类的系统上很好解决,因为基本上都会有iconv的链接库,即使没有,一条命令就装上了,但在Windows上就麻烦些,首先Windows上用CGO就要稍微麻烦点,需要首先装一个gcc编译器,比如MinGW或其衍生品。我的系统上有个msys2,上面也有iconv的链接库,直接从网上go get一个iconv的go封装package就会通过CGO试图寻找那些归档文件,但它会说找不到mingwex和mingw32的归档文件,这个问题可以通过在CGO_LDFLAGS环境变量中设置链接器搜索路径解决。
前些天看到有人移植了SSR Android版,我就顺便看了看代码,结合网上的一篇文章,觉得似乎挺简单的,它(官方也)用Java/Scala写了个外壳和启动VPN service,其他功能是几个用C写的程序共同完成,包括redsocks,tun2socks,ss-tunnel,ss-local,pdnsd。
之前说过想做个类redsocks的实现,纠结了一些天看代码后,现在终于用Go做了个初步能工作的版本出来,名字叫Avege,依然是某女推友的id。
在高中同学的公司里兼了个职,原本只说是提供技术部发展等方面的咨询和顾问等事宜的,于是我要的兼职报酬也不高。后来他说要我写个程序,做债权匹配管理,我就觉得有点坑爹了,我顺势就提要求配一个笔记本,虽然是最低配的。一直拖拖拖,一方面是确实拖延症严重,另一方面也确实觉得这东西应该工作量不大。后来做的时候发现还是有些折腾的地方的。
前段时间用ss-redir实现了后端是shadowsocks的翻墙网关,虽然真的实现了全局域网自动翻墙,但仍然留下了各种不足。
今天要把一段文本从gb2313转换为UTF-8,网上有一些第三方库,比如使用iconv之类来转换,其实有比较官方的方法:
周末两天都用于参加第一届Gopher China技术大会了,这是我第一次参加这类活动。大会在浦东软件园了的浦软大厦2楼举行,很糟糕的一点是那大会堂里联通信号都没有,我那Nexus6估计一直在尝试连接网络,一整天都烫手,电池只能撑6个小时。
之前提到的Thumbnail Service是用准备用Amazon S3来存储的,因为图省事,网管找了个s3fs把S3 bucket直接mount到本地,于是就当成本地目录一样读写。今天网管突然提到S3连接并发和性能的问题,找了篇文章看了看,大概意思是并发过多或过少性能都不好(废话)!
今天终于把Thumbnail Service的性能问题解决了。
这个项目很早前就听说要做了,一直拖拖拖,我实在很想做这个东西,周一就跟TL说,然后就简单谈了一下,确定了架构和分工,于是就开始了。
昨天花了一天时间,把github上几个Go程序通过travis实现交叉编译,再把编译生成的二进制可执行文件push回github上的prebuilt branch,这样每次有新的commit后,都会自动生成各个支持平台的最新的二进制可执行文件,相当方便。
Rust总用来跟C++,尤其是Go来对比。我也差不多学了并用了近一年的Go,基本上可以用来独自做些并不复杂的程序,最近特别想去学一下Rust,想看看到底和Go各有什么优缺点。
虽然使用Go语言写东西已经有一段时间了,但仍然不是很熟练,一些常见的用法仍然要不停地翻官方文档和搜以前写过的代码。前些天用Go的zlib包对数据进行压缩再传输,发现小数据量,比如4MB以下,总是压出结果只有2字节,这是明显有问题,实际上大点的数据量,比如5MB或更多,虽然压出的结果不是2字节了,但现在想来也是有问题的。看了很多网上的代码,发现跟我的几乎没区别。最后偶然才发现,原来是得到一个io.Writer写完后就马上关闭,再去看压缩后的结果,那时就是正确的,而我之前一直是在关闭前就去取结果了。
之前注册了搜狐云景PaaS,被送了100元的券,不过当时看了一下发现不支付Go程序,于是就没玩下去了。前几天连续收到几封邮件,说钱要花完了,也没放在心上,觉得反正玩不了,就随它去吧。今天在v2ex上看到有人说可以免费送3个月的使用配额,于是又上后台看了一下,发现它居然使用限制那么少,可以自己在配置文件中指定要运行的程序路径,这样就可以部署Go程序了,立马把之前在京东云上部署的ifconfig在搜狐云景上也部署了一个,感觉还不错。
昨天在写微信公众号文章的爬虫,中间需要解析一段GBK编码的XML,结果发现Go语言自带的encoding/xml包默认是不支持除UTF-8以外其他编码的。在网上随便搜了搜,能看到代码的方法不是过时的就是不能work的,最后还是看到比较官方的一个包可以解决这个问题,代码如下:
这两天看论坛,又想到两个对我来说比较有用的东西。其中一个是密码管理。
学Go语言已经有一段时间了,其实之前就一直在改Yiili就是用Go语言写的,但毕竟只是在别人已经比较完整的程序上修修补补而已。从周日开始总共花了近3天时间,把公司那个项目的消息转发服务器用Go语言实现了。主要还是不够熟练,很多基本的东西仍然要不停地翻说明文档和在网上查解决方案,所以比较慢,相信熟练起来后这个时间可以大大缩短。这个服务器只是个RESTful API服务器,功能也非常简单,包含了操作数据库和memcached,代码量总共才几百行,真爽快,如果用C++实现肯定不止这么点。
公司里一个小项目的方案,原本就强烈建议小正太把业务逻辑提出来,单独写个server,不要把应用层代码写到nginx push stream module里去,让人家module只做单纯的协议层数据转发。小正太一直以性能消耗要多一次请求为由想把业务逻辑合到nginx的module里去,我真是无语透了,这是多丑多dirty的设计和实现啊!好在昨天又讨论这个方案时,另一个同事基本上同意我的说法,然后两个人把小正太说得哑口无言。现在公司里的人,上到boss、CTO、Director,下到team leader、PM、普通developer,几乎都对软件工程、架构设计毫无概念,脑子里眼里只有source code。很久以前我就在想,如果有人说公司能做出现在这种产品真不容易,我肯定竭力赞同,在条件这么恶劣的情况下一群水平这么次的员工还是能开发出来每年卖上千万刀的产品,确实很不容易啊!
Tag Memcached
花了好几天时间,终于给Yiili的程序加上了Memcached和Redis的支持。前面也说过,我只是用它们来实现缓存的功能,把一些本来需要查数据库得到的数据缓存起来,比如帖子列表、话题列表、分类列表等,目前看来,效果确实是有一点的,但因为测试环境的帖子太少,还不能看出来以后帖子多起来的时候效果有多少。另外就是Memcached和Redis在效率上的区别也基本看不出来,估计也得是比较大数据量和查询操作才能比较明显得体现出来。
Tag Redis
花了好几天时间,终于给Yiili的程序加上了Memcached和Redis的支持。前面也说过,我只是用它们来实现缓存的功能,把一些本来需要查数据库得到的数据缓存起来,比如帖子列表、话题列表、分类列表等,目前看来,效果确实是有一点的,但因为测试环境的帖子太少,还不能看出来以后帖子多起来的时候效果有多少。另外就是Memcached和Redis在效率上的区别也基本看不出来,估计也得是比较大数据量和查询操作才能比较明显得体现出来。
Tag QtQuick
这两天突然想把istkani在Android跑一下,本来是想集成个腾讯信鸽的推送功能,但是信鸽没集成好(程序老是挂掉),先去调了一下界面的问题。
QtQuickCompiler出来有一些日子了,自从istkani在iOS App Store上架后,就没怎么关心过Qt的进展,只是差不多每天例行扫一遍Qt的邮件列表而已。昨天心血来潮想试试QtQuickCompiler到底有多神,首先快速浏览了一下官方文档,发现使用还是很简单的,然后开始照文档的说明一步一步操作。
Tag QtQuickCompiler
QtQuickCompiler出来有一些日子了,自从istkani在iOS App Store上架后,就没怎么关心过Qt的进展,只是差不多每天例行扫一遍Qt的邮件列表而已。昨天心血来潮想试试QtQuickCompiler到底有多神,首先快速浏览了一下官方文档,发现使用还是很简单的,然后开始照文档的说明一步一步操作。
Tag istkani
这个app在2014年就上架过,除了一开始送出去一堆兑换码以外,以每月大约不到1个付费用户的速度卖出过几份。后来也就更新过1个版本,后来就懒得更新了,直到2017年10月因长期不更新被下架了。
昨天打算提交一个istkani的新版本到app store,其实没什么更新的内容,前段时间在UI上微微调整了一下,其他原本想加的功能一直由于拖延症而没动手。只是因为iOS8发布了,Xcode也升级到了6.0.1而想试一下。结果遇到了不少问题。
昨天收到Apple AppStore的邮件,是八月份的Financial report,原来八月份居然卖出了两份istkani,真是太让我意外了。本来自五月份上架以来,除了兑换码送出几十份以外,我就没怎么指望能把它卖出去的,虽然也有过一些升级的计划,增加新特性以及提升UI设计等等,不过后来还是一直拖延着。
QtQuickCompiler出来有一些日子了,自从istkani在iOS App Store上架后,就没怎么关心过Qt的进展,只是差不多每天例行扫一遍Qt的邮件列表而已。昨天心血来潮想试试QtQuickCompiler到底有多神,首先快速浏览了一下官方文档,发现使用还是很简单的,然后开始照文档的说明一步一步操作。
Tag JIT
QtQuickCompiler出来有一些日子了,自从istkani在iOS App Store上架后,就没怎么关心过Qt的进展,只是差不多每天例行扫一遍Qt的邮件列表而已。昨天心血来潮想试试QtQuickCompiler到底有多神,首先快速浏览了一下官方文档,发现使用还是很简单的,然后开始照文档的说明一步一步操作。
Tag C++
这几天突然又想试试C++ Builder,现在最新的版本是12.1。曾在大学时使用C++ Builder 6写过一些小程序,这么多年过去,源代码丢掉了一些,还能找到一些。用12.1是不能直接打开6.0的工程文件的,需要新建VCL工程,再把窗体文件、源代码文件和头文件添加进去,才能编译。12.1的VCL整体上变化不大,主要是字符串类变成了UnicodeString,以前的C++ Builder和Delphi在字符编码方面的支持确实是一大弱项,项目代码拷过来后,主要就是字符串部分需要修改一下。
英文原文:https://www.modernescpp.com/index.php/thebigfour
C++20,近十年来最具影响力的C++版本,完成了!
原文:https://www.reddit.com/r/cpp/comments/f47x4o/202002_prague_iso_c_committee_trip_report_c20_is/
偶然在Embarcadero的营销邮件中发现现在C++ Builder有Community Edition即社区版可以免费下载使用,想当年从大一买了自己第一台电脑开始,也曾用过6年左右C++ Builder写了些小程序,为了情怀也得试用一下。
QtQuickCompiler出来有一些日子了,自从istkani在iOS App Store上架后,就没怎么关心过Qt的进展,只是差不多每天例行扫一遍Qt的邮件列表而已。昨天心血来潮想试试QtQuickCompiler到底有多神,首先快速浏览了一下官方文档,发现使用还是很简单的,然后开始照文档的说明一步一步操作。
Tag car
国家大力推广不停车支付过路费,虽然我高速跑得不少,但我一直嫌麻烦没去安装ETC,从新闻上看到有些省份已经试行微信支付和支付宝支付了,像上海的虹桥火车站、机场停车场我在支付宝上绑定了车牌后,也可以自动感应支付了,结果到现在也没等到这两家侵入到这边的高速公路收费站,倒是等来了年底普及ETC。
中秋回家的时候闲得无聊玩手机上百度地图,偶然发现8月份居然突然多出10次违章记录,几经查询确认,是那段时间经常早上上班时顺便往那边买早点然后走到单向行驶的路上逆行了。如果不是闲得无聊,怕是要这样被抓几百次了!
早上出门打算开车上班,刚起步就听到有奇怪的声音,像是什么东西卡住了,下车绕着车看了一下4个轮胎,似乎是正常的,再起步,声音还是很大,踩刹车的时候声音特别大,于是只好决定不开车了,等周末的时候找家修车的检查一下,真烦躁!
周一去换了驾照,因为本人去深圳实在不现实,在网上看到可以直接转成上海驾照,于是就这么弄了。花了450元钱,就在车管所对面,一座要被拆掉的小楼里面,很山寨的问了一问“你开车的时候戴眼镜么”,这大概就算是体检了,然后在另一个房间里拍了张照,交了钱把身份证、临时居住证以及旧驾照留下就可以走了,隔一天就会用顺丰把这些证件送过来。明明走正规流程非常复杂繁琐的,只要交点钱就能非常便捷,这就是天朝现状,可谓生财有道!
今天早起送妹子去了火车站,回来休息了一下便出门办事。因为我的驾照快到期了,原本是深圳发的如果要在深圳续期的话非得本人跑去深圳不可,不光是要拍带回执的照片只有深圳的照相馆连得上深圳的相关部门的网络,指定的体检的医院还只有深圳的,所以对我来说成本过于巨大。好在后来网上搜了一下,像我这种情况的人可以直接在上海把驾照转成上海的,只要去指定的地点带上身份证、(临时)居住证和旧驾照,以及几百块钱,当天就可以把拍照和体检等所有手续都办完,顺便续期。因为我的临时居住证早已过期,我今天就打算先去续一下,于是先跑到居委会所在,大门紧闭,一张工作时间贴在门上,只有工作日才开放。怏怏离开,抱着试试看的心理去了镇上的社区服务中心,一问果然还是要居委会开的居住证明。只好下周一请假了!损失真不小啊!
Tag startup
周一去换了驾照,因为本人去深圳实在不现实,在网上看到可以直接转成上海驾照,于是就这么弄了。花了450元钱,就在车管所对面,一座要被拆掉的小楼里面,很山寨的问了一问“你开车的时候戴眼镜么”,这大概就算是体检了,然后在另一个房间里拍了张照,交了钱把身份证、临时居住证以及旧驾照留下就可以走了,隔一天就会用顺丰把这些证件送过来。明明走正规流程非常复杂繁琐的,只要交点钱就能非常便捷,这就是天朝现状,可谓生财有道!
Tag Financing
这两天看论坛,又想到两个对我来说比较有用的东西。其中一个是密码管理。
Tag toy
妹子生日的时候她表妹送了一个Bridestowe牌的薰衣草小熊给她。当时的多开心的,在电视上看到过某演艺圈的明星就是做这个生意的,在国内受到热捧。前段时间我在淘米的时候偶然发现这才买来没多久的袋装大米里居然有一两只米虫,虽然觉得这种品质的大米里会长米虫很奇怪,但因为小时候自家种自家碾自家吃的米里常常会有大量的米虫出现,多的时候甚至能听到“沙沙”的虫爬的声音,记得那时候爸爸还买来那种杀虫的药粉来撒在上面,所以我也没怎么当回事。前些天妹子突然发现放在床头的薰衣草小熊外面爬了好多米虫,幸亏外面套了个纱袋,才没让虫子大规模分布在整个屋里,但想来已经有一些能飞能爬的跑到外面去了。
Tag Bridestowe
妹子生日的时候她表妹送了一个Bridestowe牌的薰衣草小熊给她。当时的多开心的,在电视上看到过某演艺圈的明星就是做这个生意的,在国内受到热捧。前段时间我在淘米的时候偶然发现这才买来没多久的袋装大米里居然有一两只米虫,虽然觉得这种品质的大米里会长米虫很奇怪,但因为小时候自家种自家碾自家吃的米里常常会有大量的米虫出现,多的时候甚至能听到“沙沙”的虫爬的声音,记得那时候爸爸还买来那种杀虫的药粉来撒在上面,所以我也没怎么当回事。前些天妹子突然发现放在床头的薰衣草小熊外面爬了好多米虫,幸亏外面套了个纱袋,才没让虫子大规模分布在整个屋里,但想来已经有一些能飞能爬的跑到外面去了。
Tag socket
之前遇到一个bug,一直想不通为什么会出现。具体现象是程序一直尝试去连接一个没打开的端口,过一段时间,可能是几分钟,也可能是几天,那个端口突然被程序自己打开并连上了,然后读到了一些计划外的东西接着断言失败了。我仔细检查过整个程序的代码,有哪些可能会打开一个新的端口,结果没有发现。后来用gdb挂上跑,在listen,bind之类的函数打断点,也没见hit,但bug仍然出现了。
之前说过,我把一个项目中的程序线程数都尽量减少了,差不多就是一个程序用一个线程来跑一个event loop来服务所有socket,结果这几天发现似乎性能有点跟不上了。
到今天为止,IPC协议的重构也进行了一部分,效果不错。原本每秒一次的查询是否有新命令,现在使用阻塞式的查询,有新命令会立即到达,可以立即执行,原本一条新增instance的命令要大概3秒才能得到回应执行完毕,现在基本上下发命令就立即能得到回应了。同时删除instance命令也由原来的平均0.5秒耗时变成立即完成。
前面提到过,因为了读了一点《Linux多线程服务端编程》,觉得自己对网络编程有了更多的了解,可以对公司里负责开发维护的那个小项目动手重构了。这个小项目从功能上简单说来,就是个流量转发器,也可说成是个中断器,所以项目名称就叫Relay了。几乎每个刚听到这句话的人,都会第一时间发出疑问:这种功能网上开源代码或现成工具应该有很多,比如nginx就有类似的功能,为什么要自己做一个?答案可以从两个方面来回复,一种霸道无理点的说法是,这是公司策略,这个理由足以堵住所有质疑者的嘴巴。另一种理性点的说法是,自己做可控性好,可扩展性也好,比如我们要有实时的流量统计,我们要自定义高效的传输协议,像nginx的http传输性能不能完全满足我们的需求等等。
其实我大概10年前就知道ACE了,并且把国内翻译引入的3本以ACE为蓝本的讲C++网络编程的书都收齐了,之所以说是收齐,是因为自己买了两本《C++网络编程》,而由译者马维达送了一本ACE开发指南。但是三本书入手后并没有认真读过,后来工作上也跟C++网络开发基本不相关,于是一直了解不多。直到现在这份工作,虽说终于转向网络开发了,但实际上要么因为老代码已经把底层封装好了,要么就直接用了Boost.Asio而不求甚解。
Tag network
前面提到过,因为了读了一点《Linux多线程服务端编程》,觉得自己对网络编程有了更多的了解,可以对公司里负责开发维护的那个小项目动手重构了。这个小项目从功能上简单说来,就是个流量转发器,也可说成是个中断器,所以项目名称就叫Relay了。几乎每个刚听到这句话的人,都会第一时间发出疑问:这种功能网上开源代码或现成工具应该有很多,比如nginx就有类似的功能,为什么要自己做一个?答案可以从两个方面来回复,一种霸道无理点的说法是,这是公司策略,这个理由足以堵住所有质疑者的嘴巴。另一种理性点的说法是,自己做可控性好,可扩展性也好,比如我们要有实时的流量统计,我们要自定义高效的传输协议,像nginx的http传输性能不能完全满足我们的需求等等。
其实我大概10年前就知道ACE了,并且把国内翻译引入的3本以ACE为蓝本的讲C++网络编程的书都收齐了,之所以说是收齐,是因为自己买了两本《C++网络编程》,而由译者马维达送了一本ACE开发指南。但是三本书入手后并没有认真读过,后来工作上也跟C++网络开发基本不相关,于是一直了解不多。直到现在这份工作,虽说终于转向网络开发了,但实际上要么因为老代码已经把底层封装好了,要么就直接用了Boost.Asio而不求甚解。
Tag asyc
其实我大概10年前就知道ACE了,并且把国内翻译引入的3本以ACE为蓝本的讲C++网络编程的书都收齐了,之所以说是收齐,是因为自己买了两本《C++网络编程》,而由译者马维达送了一本ACE开发指南。但是三本书入手后并没有认真读过,后来工作上也跟C++网络开发基本不相关,于是一直了解不多。直到现在这份工作,虽说终于转向网络开发了,但实际上要么因为老代码已经把底层封装好了,要么就直接用了Boost.Asio而不求甚解。