2008年2月25日星期一

小看了Lua

虽然我一直对于脚本语言比较偏爱,但也一直没把Lua看上眼,认为它功能太弱了,只能“螺蛳壳里做道场”;而喜欢这个东西的似乎也都是搞C++的那些喜欢研究语言技巧的人。

但今天无意翻了一些wxLua,对这个东西有了兴趣,然后又顺便看了一些Lua本身,发现这个东西以前还真没意识到它的价值。

先拿wxLua来说,wxWidgets有不少脚本语言的binding,从wxPython, wxRuby到wxJS, 其实差别都不是特别大,但wxLua有些不同,至少它在使用模式上很适合于这样一种情况:快速开发一些小的程序(其它方面我还没来得及考虑,暂且不提)。

一 方面,适合这种情况的东西很少: 虽然可以用wxPython快速开发,但对于做一个程序来说,发布起来比较麻烦(py2exe还是有些够折腾的);Visual Basic和Delphi这类工具,可以快速开发,发布程序也方便(抛开VB程序采用的ActiveX库不谈),但它们是商业软件,同时又是庞然大物。所 以我看见一些同事用Excel的VBA来开发一些简单程序,也有比较geek的人学习AutoIt

另 一方面,wxLua自己也做得很适合这个。从规模上而言,wxJS比wxLua大不了多少,但wxLua将脚本解释器、wxWidgets对象全都做到了 一个可执行程序中,不需要任何动态库;它还提供了一个wxLuaFreeze工具,可以将Lua脚本跟这个解释器绑定到一个文件,用法相当简单,并且还可 以采用UPX这类工具对最终程序进行“透明”压缩。

这样来看,lua算是一个非常好的胶水语言(glue language), 在表现上可以嵌入在程序中完全隐形,同时带给程序的累赘也少(至少我们的产品目前采用Active Scripting就必须得将可脚本化的对象包装成COM对象,这个工作量可大了去了)。

不过,“五行拳”(Programming in Lua中文翻译版中引用了一段金庸《碧血剑》里的文字,意在比喻“极寻常的拳术",只要练习得好了,”每一招均是含劲不吐,意在拳先,举手抬足之间隐含极浑厚的内力”)也有一点点不爽,比如我现在想在wxLua的脚本代码中操纵COM对象,就得仔细琢磨怎么将LuaCOM的代码合进来才行,回头要另外一个功能又要合代码,这种情况可能还不如py2exe方便了(不过还没琢磨过Lua的代码,不知道何如这些特性简单不)——但“需要什么才加什么”这种方式也挺不错的。

2008年2月9日星期六

wxWidgets和MFC混合编程

很多文章都讲到了将MFC程序迁移到wxWidgets上(首先要读的也许是IBM developerWorks上这篇 将MFC应用程序移植到Linux),但对于一个比较大的程序,要一下子完成移植也显得有些艰巨。所以我在琢磨有没有可能在一个程序中同时使用这两种技术(同时我看中了wxWidgets上使用wxPython时给应用程序带来的可扩展性,有兴趣的可以查看wxPython中的这个embed示例)。

wxWidgets的代码库中倒是有一个wx和MFC混合的例子(发布出来的2.6的代码包里面好像没有,2.8才有),它演示了如何在一个程序中分别有wx和MFC的窗口(分属于wxFrame和CFrameWnd类)。

但它没有解答的问题是:怎样将一个wx的控件放到MFC上面去,或者反过来

在这个例子中,如果你想将wx的窗口作为应用程序开始时显示的窗口,就需要这个:
   m_pMainWnd = new CDummyWindow((HWND) wxTheApp->GetTopWindow()->GetHWND());
如果你了解MFC对窗口的封装,就知道它基本没有自己的东西,CWnd这些类基本上没有自己的数据成员,基本上都是调用Windows API(只是把那些API中的HWND参数给省略了。所以任何一个Windows桌面上的窗口,要体现为一个CWnd类对象是很容易的,只需要调用CWnd::FromHwnd()或者CWnd::Attach()就可以了,示例中的CDummyWindow就是这样做的。基于这样的思路,我们很容易把其它的wx控件通过CDummyWindow放到MFC控件中去。
wxTreeCtrl * wxtree = new wxTreeCtrl(.....)
CDummyWindow *dummy = new CDummyWindow((HWND)wxtree->GetHWND());
dummy->SetParent(this);

我们需要其实不要CDummyWindow也没有问题,只要这样:
wxTreeCtrl * wxtree = new wxTreeCtrl(....)
::SetParent(HWND)wxtree->GetHWND(), m_hWnd);
但这里有另外一个问题: 创建一个wxWindow对象时是必须给出一个parent的,而这个parent又必
必须是wxWindow类型(除非为NULL)。

反过来要将MFC的东西放到wx上面就可以那么好运了,虽然也可以用上面这一招将MFC的控件显示出来,
但这些控件低于wx来说是透明的,你没法利用到wxSplitterWindow的分割功能,没法利用上各种layout manager/sizer。

wxWidgets For MFC Programmers(from wxWidgets Wiki)中讲述了如何将一个CWnd转换为wxWindow对象:

wxWindow * win = new wxWindow();
win->SetHWND((WXHWND)hWnd);
win->AdoptAttributesFromHWND();
win->Reparent(wxGetApp().GetTopWindow());

2008年2月8日星期五

终于将blog迁移完成了

从去年初开始将blog迁移到Blogger上,直到今天,才算终于完成了。

我原来的blog在Linux伊甸园上(巴蛮子的新破茅屋),开始有迁移的想法是在去年初,主要的原因是Linux伊甸园提供的Blog服务经常当机,并且每次出了故障之后,总会有一些文章丢失(这几个月陆续按以前的一些本地“备份”来重新发帖,才发现差不多丢了1/3)。

但一直也不直到迁移到哪里去好,试过blogbus, CSDN, chinaunix,最后基本上觉得Blogger功能上比较适合我这Blog的风格,而且Blogger提供的版面编辑功能还是挺好使的。

但中间又犹豫、反复,一方面因为国内常常无法访问blogspot.com,另一方面otto老大又热情地邀请我回去,我也在试用linuxeden

但最终Blogger的"自定义发布位置"这一功能让我觉得还是采用Blogger了:我可以在其它地方申请一个网站,然后采用ftp/sftp发布方式,将所有文章发布到这里(目前的镜像是 http://bamanzi.inlsd.org/blog ),这样一方面可以解决blogspot.com无法访问的问题,另一方面我可以通过ftp将所有文章备份下来。

不过搬迁过来,文章不会在其它地方出现,访问的人也少了。反正这一年我写得也少了,凑合着过吧。