なぜUnifinityでは共通のエンジンが異なるOSで動作するのか

テックポエム

Unifinityが世に出てから3年ほどが経ちます。その間、何度かのバージョンアップがあり、プログラムの大幅な変更を行って、操作や見た目が大きく変わったりしたこともありました。しかし、Unifinityの主な機能をつかさどるコアエンジンには、Unifinityの開発当時から存在しているコードが残っていたりします。
それはUnifinityのアーキテクチャにかかわる部分で、Unifinityが管理するイベント処理の基本的な部分や、Unifinityで様々なデータを扱う機能だったりします。
そんな中でも、本日は「Rosetta」と「Bridge」と呼ばれている部分について記事を書いていこうと思います。

・言語間のやりとり
Unifinity Application Playerはネイティブアプリなので、Windows版はC#、iOS版はObjective-C、android版はJavaで記述されております。一方、アプリ内に組み込まれているUnifinityのエンジンは、OS毎の差異を吸収するためにC/C++で記述しております。
各々の言語は独自の世界を持っているため、複数の言語を同一アプリ内で動かすためには、言語間を行き来するための仕組みが必要となります。
これを解決するために用意した機能が、前述した「Rosetta」と「Bridge」です。

1.jpg

※By Rich Niewiroski Jr. (http://www.projectrich.com/gallery) [CC BY 2.5  (https://creativecommons.org/licenses/by/2.5) or Attribution], via Wikimedia Commons

「Bridge」は文字通り「橋」の機能を有します。各言語を「島」と見立てて、別の島に渡るための機能をイメージして名付けました。
Unifinityでは、各ネイティブの言語からC/C++という島に渡るため「Bridge」はそれぞれの言語で次のようなことをしております。
まず、C#で開発しているWindows版はDLL呼び出しを利用します。UnifinityのエンジンをDLLとして生成しておき、C#からDLLの機能を呼び出すことで、連携を実現しております。また、Javaで開発しているandroid版では、NDKを利用してエンジンを静的ライブラリとして作成し、それをリンクして連携しております。iOSで使用しているObjective-CはC/C++と互換性があるため、そのまま直接呼び出すだけで連携を行うことができました。
こういった言語間をつなぐ「Bridge」の機能によって、OS毎に開発言語は異なるUnifinity Application Playerでも、C/C++で構築された共通のエンジンを活用できるようになっているのです。

2.jpg※British Museum [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC BY-SA 4.0  (https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia Commons

・Rosetta
「Rosetta」は、OS毎の挙動の差異を、Unifinityエンジンが解釈可能な形式に変換する機能を持っています。
例えば、ユーザーが画面上のボタンを押すことを考えてみます。
Windowsでは、それはマウスクリック(MouseDown/MouseUp)になりますが、android/iOSではタッチイベント(Touch)として扱われます。画面を押したままでマウス/指をずらすと、ドラッグやスワイプの操作になったりもします。またタッチイベントの場合は、複数の指が触れているかもチェックしなければいけません。
このようにボタンを押したときにどのような挙動となるかは、OSや操作方法によって異なっています。

そこでUnifinityでは、エンジンが解釈できるイベントを抽象化することで対応しております。例えば、先ほどの「ユーザーが画面上のボタンを押す」は「PointerDown」というイベントとして定義しております。
マウスでタッチしても、指でタッチしても、スタイラスペンでタッチしても、Unifinityの「PointerDown」というイベントが発生した、と変換することで、どのOSでUnifinityアプリケーションの操作をしても、同じような操作を行うことができるわけです。
このように、各OSにおいてユーザーが何か操作を行った際に、Unifinityが定義するイベントへデータの変換を行うのが、このRosettaの主な役割となっております。

このRosettaという名前は、エジプトで発見された「ロゼッタ・ストーン」から命名させていただきました。「ロゼッタ・ストーン」は「ヒエログリフ・デモティック・ギリシャ文字」の3種類の文字で同じ文章が書かれているものなのですが、上記「異なる言語で同じことを書いている」という構造が「ロゼッタ・ストーン」と似ていたため、この名前としました。(この命名はかなり気に入っております)


・C/C++と共に生きる
「Bridge」や「Rosetta」等の機能により、Unifinityエンジンは、OSのネイティブ機能をフル活用しつつ、OS毎の差異を吸収するという構造をとっております。

今後新しいOSが発表され、そのOS向けの新しいUnifinityエンジンの開発を行う場合でも、そのOSで「Bridge」と「Rosetta」さえ作ることができれば、そのOS向けのUnifinityエンジンを開発することが可能です。また、そのOSが今までとは異なるインターフェース(例えば視線で操作する、脳波で操作する)を持っていたとしても、それをRosettaでUnifinityのイベントに変換(EyeBlinkDown→PointerDown)
すれば、Unifinityアプリケーションを操作することができます。

Unifinity開発当時にはSwiftはまだありませんでしたし、昨年は、AndroidがKotlinに対応するという発表もありました。このようにネイティブアプリを開発できる言語は変わっていくことが予想されます。

しかし多くのシステムのベースに使用されているC/C++言語は無くならないと考えております。それは、世の中にあるあまりにも多くのライブラリ・システムがC/C++で構築されているからです。もしなくなるとしても、必ず互換性を持つラッパーライブラリがあらわれると考えております。


ところで、先日発表した新プロダクト「Unifinity Flow」でも、Unifinityのエンジンをそのまま使用しております。(このため、Unifinity Flowで作成した画面は、Unifinity Studioでもそのままの見た目で編集することができるのです!)また、夏に発表した「UniForm」は、Excel帳票の定義をUnifinityのエンジンが解釈できる形に変換することで、Excelの見た目や機能はそのままにモバイルアプリ化するというプロダクトでした。
まだまだUnifinityのエンジンには描画面や機能面に拡張の余地があるので、今後もこのエンジンを改良しつつ、Unifinity Platformが実現できる世界を広げていきたいと考えております。