Wednesday, June 29, 2011

Embedding Lua for scripting




最近 Lua 似乎挺火。它被設計爲一門輕量級的、可供嵌入到其它語言作爲膠水 (Gluing) 的語言。
一直很好奇這是怎麼做到的,於是仔細研究了一下,在網上發現了這篇文章,作者提供了一個 minimal 的源代碼。
閱讀完大概明瞭,但原來的程序有些 bug,而且有些小細節沒有說明清楚(比如,原文基於 Lua 5.0,但最新的 Lua 5.2 有 major changes)。
於是 fork 之修改完成,並記錄如下。

Disclaimer:
正如作者聲明,裏面的 C 以及 Lua 都沒有寫得非常優美或規範。
由於是做示範性用途,所以許多地方都採取了 quick & dirty 的方法,還有各種 magic number。
雖然在代碼裏沒有標明,程序版權屬於原作者。

Prerequisites:
OS X (測試環境,10.6.8 ) / Linux (原文提到支持,但未測試。不過沒道理不成功 :p )
Lua 5.2 & liblua:
- 在 OS X 下, 可以安裝 Lua.framework,我用的是自己編譯的版本。
- 在 linux 下,可以通過各種包管理工具直接安裝 lib 以及 interpreter。
注: LuaJIT 應該也可以,但現階段尚未更新至 5.2 compatible
pkg-config
SDL 1.2.14: OSX 可直接下載 SDL.framework,注意必須 copy sdl.dmg 裏面的 devel-lite 裏面的 SDLmain.{m,h},以把程序包裝成一個 Cocoa 程序。Linux 無此問題。
OpenGL

介紹及原理:
Python/Ruby/Lua 之類的語言都可以作爲嵌入式的語言使用,然而 Lua 以其簡潔的語法、支持多範式編程以及極小的庫體積(~100K),受到衆人的青睞。
它被大量運用在 Game Programming 裏,比如魔獸世界(WoW)就是用它來做各種 extension 的。
這些動態語言比起編譯型語言的主要好處,就是更加抽象,更加高層次,支持 Functional programming, 有各種語法糖衣輔助等寫出 human-readable 的簡潔代碼。
不足之處在於,本質上它們的運行都需要經過一層中間層—— Virtual Machine 來與系統底層進行交互。所以效率往往比起 C/C++ 等要低。
所以人們想出了一個好方法:主要的程序邏輯使用 scripting language 編寫,而一些要求高性能或者底層的代碼段,則還是由編譯語言完成。
這裏有一份更詳細的介紹文檔。示意圖來自該文檔。



程序流程:
程序本身應該是一個編譯型語言生成的程序,在裏面提供了各種基礎設施,如繪製圖形等。
在程序裏面會鏈接到腳本語言的庫,然後主要的工作在腳本語言裏面完成,比如定義各種 Object,
它們之間的 interaction 等。這裏可以看到另外一個好處:一些經常需要改動的值,我們不需要
寫在C/C++裏,因此不需要重複編譯程序,而只需要把它們保存在腳本文件裏即可方便讀出。
因此腳本語言也可以當做配置文件使用。

The Pong Game (這個遊戲不用介紹了吧?):



讓我們來看看具體是怎麼實現的。在這裏採用了 C+Lua 的組合。
在 C 程序裏,定義了如何繪製榘形 (draw_rectangle),以及處理方向鍵的函數(由 SDL 提供)。
以上的函數都被 register 到 Lua 裏面(具體來說,是程序運行后生成的 Lua VM instance)。
而 C 裏也可以通過 Lua 提供的 API 調用 Lua VM 定義的函數。
在這裏,是一個名爲 "pulse" 的函數 (好吧, 老外覺得這個詞很直觀形象, 請深入理解...)
在初始化好 SDL 的一些咚咚後, 程序進入 main loop.
如果寫過 OpenGL 或者 Win32 之類的採用事件模型 (Event model)的程序, 就知道這個
main loop 拿來做什麼的. 基本上, 這個 main loop 就是監聽外部輸入 (這裏是鍵盤),
每次循環會間隔一定時間, 並調用 Lua 的 pulse 函數進行畫面的更新.

在 Lua script 裏, 定義了兩個類, 分別是作爲板子的 paddle 以及球 ball.
當程序運行后, Lua 會創建兩個 paddle 以及 一個 ball 並更新它們的位置.
如果有按鍵事件, 則根據它更新 paddle 的位置; 同時也進行碰撞檢測.

簡單來說:
(in C) main loop -> call Lua pulse -> (in Lua) crash detection, drawing (call C's draw_rectangle) -> (in C) main loop ...
That's all!

Note: 原來版本的程序裏, 如果 ball 飛出了 y 方向, 則它真的飛了出去...
於是我稍微改了一下腳本, 增加了 y 方向的邊緣碰撞檢測.
注意, 這裏完全沒有改 C 程序代碼或編譯, 而是直接修改腳本即可.
可以修改的地方還有很多, 比如改變 paddle 的大小, 球的速度, 電腦 AI 等.
另外, x 方向上的碰撞檢測也沒有完成 :)

我適當地在源代碼裏加上了一些註釋, 需要知道得更清楚的, 可以 RTFSC.

Tuesday, June 28, 2011

用DNS隧道实现免费上网

 
 

Sent to you by Ivan Z. Siu via Google Reader:

 
 

via FeedzShare 1天最热 on 6/27/11

来自: Creke Blog - FeedzShare  
发布时间:2011年06月20日,  已有 5 人推荐


大多数机场、酒店之类场所,当你输入一个网址比如www.google.com时,会弹出一个页面要你输入帐号密码才能上网。这个时候DNS能正确解析,但是上网要付费认证。

可以通过DNS隧道来实现免费上网。具体做法是:

(1)找一个支持DNS解析的域名,现在这类免费域名很多,比如tk的、co.cc的。假设该域名是

abc123.tk

(2)在tk的注册机构里,设置abc123.tk的NS服务器为你自己的主机(最好是Linux VPS),例如:

abc123.tk.     IN  NS  ns.abc123.tk.
ns.abc123.tk.  IN  A   74.81.81.81

(3)在74.81.81.81上,以root身份运行一个Perl脚本(这个脚本来自Dan Kaminsky的OzymanDNS包):

./nomde.pl -i 0.0.0.0 abc123.tk

上述脚本会侦听在UDP 53端口,接受DNS请求,并且只解析abc123.tk域。

(4)在客户机上(要求有ssh,最好是Linux系统),运行如下命令:

ssh -ND 7070 -o ProxyCommand="./droute.pl sshdns.abc123.tk" user@localhost

上述ssh命令,-ND 7070表示在本机打开7070的socks 5代理端口。droute.pl是DNS隧道的客户端工具,同样来自于OzymanDNS包。sshdns是固定的主机名,加在域名abc123.tk前面。user是你在74.81.81.81上的登录名字,@localhost是固定的,不需要改(因为隧道过去后,就是74.81.81.81本机)。

运行上述ssh命令后,会提示输入密码。输入正确密码后,就和远程主机建立了ssh连接,获取到一个SSH终端。并且,在本机打开了7070的socks 5代理端口。配置浏览器使用这个代理端口,开始享受免费冲浪吧!

 

转自:http://www.nsbeta.info/archives/96


 
 

Things you can do from here:

 
 

Wednesday, June 22, 2011

关于 Mac 自带的 Cairo, libpng

Cairo
=====

最近在编译一些 graphics 有关的程序碰到了这个问题:
Mac 自带了 Cairo 库, 但是版本已经很老了 (1.8.6).
许多程序都要求 >= 1.10.0
从brew里安装了新的 cairo, 由于brew为了防止破坏原先系统上的软件依赖, 因此没有为pkg-config安装对应的 .pc 文件.
因此, 我在编译 pycairo 时, 还是会找到旧的 cairo.
解决方法很简单, 当需要用到新版本cairo时, 可以:

 1. export PKG_CONFIG_PATH=/path/to/cairo/pc/file   这样, pkg-config就会找到新版本cairo的.pc文件.
 2. 使用正确的 LDFLAGS 和 CPPFLAGS 进行编译.

由于 pycairo 使用了一个叫 waf 的东西进行编译, 而我有又没找到在哪里定义方法2所提到的变量,
因此只能使用方法1.

libpng
=======
Mac 自带了 X11.app (也叫 XQuartz), 是 Apple 版本的 X11, 基于 Xorg. 里面自带了 libpng 1.2.
最新版本的 XQuartz 使用了 libpng 1.4. 但是安装了它会造成许多 confusion. 而旧的 X11.app 用起来也没什么大问题.
于是最好把新的 XQuartz 卸载掉.
具体方法见:

主要是:

sudo rm -rf /opt/X11* /Library/Launch*/org.macosforge.xquartz.* /Applications/Utilities/XQuartz.app /etc/*paths.d/*XQuartz
sudo pkgutil --forget org.macosforge.xquartz.pkg