2014年4月19日 星期六

Node.js 的原罪,和 QML 的不合作運動

Standard
在上個星期剛結束的 OSDC.tw 2014 活動上給了一個 Talk ,提及用 Node.js 結合 QML 來開發應用程式,讓我們可以使用 Node.js 和 JavaScript 來寫 QML 元件,不需要再使用 C/C++。事實上,這樣的技術看起來簡單,但實際上是困難重重。

其實,要做 Qt 的 Node.js binding,有很多問題要克服,最直接的不外乎是 Event Loop,Node.js 本身是 JavaScript 語言,所以有自己的事件引擎,而 Qt 是一個圖形界面的 Toolkit,一樣也有自己的事件引擎,因此,我們要再解決一次與過去整合 GLib 一樣的問題(詳見舊文:探究如何整合 GLib Main Event Loop 和 Node.js 的 libuv),只不過這次要實作的是 Qt 的 QAbstractEventDispatcher。

為了讓 Node.js 可以順利驅動 Qt,筆者之前花了一些時間研究,所以有了一個實驗性質的 Project 『Brig』在 Github,也為了 Qt 重新寫了一個新的 libuv 版本的 EventDispatcher。很幸運的,在實作完新的 EventDispatcher 後,已經可以順利的將 Node.js 和 Qt 的 Event Loop 接起來。

但別高興的太早,還有個大問題存在。Qt 5.2 之後將 QML 內的 V4 JavaScript 換成了 Google V8 JavaScript Engine,並且為了一些特性,修改了 V8 的部份實作。很不巧的是,Node.js 的核心也是 V8,這意味著,如果我們使用自己的 Node.js Binding 去建立 QML Engine,程式會馬上崩潰並結束(Segmentation Fault)。

種種問題,你可以說這是 Node.js 的原罪所致,這也是為什麼相當難幫 Qt 寫一個 Node.js 的 Binding,你在 NPM 上也根本找不到良好的 Qt Module 存在。最終我們的做法,還是修改了 Node.js 的部份程式,才能將他們整合在一起。