Slide 1

Slide 1 text

うかがか 伺か on Browser デスクトップマスコットをブラウザ移植してみた 利用者視点の Emscripten とその周辺

Slide 2

Slide 2 text

自己紹介 佐藤隆人 ( な ら ざ か 奈良阪 ) Twitter: @narazaka Github: @Narazaka npm: @narazaka CPAN: NARAZAKA ドリコム 2015 新卒 (2 年目 ) サー バー サイド Ruby 書いてます Perl / JavaScript / Ruby / C# あたりが好き その他 : 伺か / 漫画読み描き / OP アニメ愛好家 / 鉄

Slide 3

Slide 3 text

※ 注意 1 から 10 まで趣味の話です プロダクションレベルの知見ではありません。 試行錯誤の途中なのでアドバイスなどいただけると幸いです。

Slide 4

Slide 4 text

近年やってる趣味

Slide 5

Slide 5 text

うかがか 伺か 2000 年頃に一部で流行ったデスクトップマスコット

Slide 6

Slide 6 text

デスクトップマスコットのなかま? たち ポストペット ペルソナウェア デスクトップのメイドさん いもうとデスクトップ まいんど・ ふぉ~ かす お座りマルチ

Slide 7

Slide 7 text

かわいい

Slide 8

Slide 8 text

かわいい

Slide 9

Slide 9 text

懐かしい

Slide 10

Slide 10 text

懐かしい

Slide 11

Slide 11 text

なんかすごい

Slide 12

Slide 12 text

キャラクター 表現プラットフォー ム 16 年目の現在もたくさんのキャラの更新がある

Slide 13

Slide 13 text

しかし…… 世はスマホ全盛

Slide 14

Slide 14 text

「 キャラクター の居場所 デスクトップ」 の消滅

Slide 15

Slide 15 text

…… スマホでも使いたい ブラウザにのせて動かせないか?

Slide 16

Slide 16 text

「 伺か on Browser イカガカ」 プロジェクト コー ド https://github.com/Ikagaka デモ http://ikagaka.github.io/Ikagaka.demo/

Slide 17

Slide 17 text

ブラウザに載せるにあたって…… うかがか 伺か はどういうプログラム?

Slide 18

Slide 18 text

うかがか 伺か (materia.exe) キャラクター デー タを差し替えられる デスクトップマスコットランタイム → クロー ズドソー スなので JavaScript で新規開発 キャラクター の人格は任意の Windows 用アンマネー ジド DLL をそ のまま動作させる仕様 ( めっちゃ自由 ) extern "C" ̲̲declspec(dllexport) BOOL ̲̲cdecl load(HGLOBAL h, long len); extern "C" ̲̲declspec(dllexport) BOOL ̲̲cdecl unload(); extern "C" ̲̲declspec(dllexport) HGLOBAL ̲̲cdecl request(HGLOBAL h, long *len); →OSS の C++ 製人格 ( 台本 ) 記述用言語 DLL(.so) がいくつか存在

Slide 19

Slide 19 text

各人格記述用言語 DLL (with Hello, World!) shiori.dll ( 華和梨 8) / shiori.dll ( 華和梨 7) System.Callback.OnGET: Hello, World! satori.dll ( 里々) * Hello, World! yaya.dll (YAYA) / aya5.dll ( 文 5) request { "Hello World!" }

Slide 20

Slide 20 text

_ 人人人人人人人_ > Emscripten  <  ̄Y^Y^Y^Y^Y^Y  ̄

Slide 21

Slide 21 text

Linux で依存なくコンパイルできる C++ だった ( 一部 boost はずした ) 既存のコー ドほぼ変更なし

Slide 22

Slide 22 text

Makefile もフラグ追加と g++ ‑> em++ rem emsdk1.25.0 on Windows emcmdprompt.bat D: cd kawari make

Slide 23

Slide 23 text

各人格記述用言語 DLL 割とすんなり変換できた shiori.dll ( 華和梨 8) ‑> kawari.js shiori.dll ( 華和梨 7) ‑> kawari7.js satori.dll ( 里々) ‑> libsatori.js yaya.dll (YAYA) ‑> yaya.js aya5.dll ( 文 5) ‑> aya5.js

Slide 24

Slide 24 text

_ 人人人人人人人_ > Emscripten  <  ̄Y^Y^Y^Y^Y^Y  ̄ ‑ 完 ‑

Slide 25

Slide 25 text

! ここからが問題 ! ~Emscripten とその周辺~

Slide 26

Slide 26 text

今回の最重要要件 = 互換動作 キャラデー タの変更なしに デスクトップと同じ挙動を保証したい キャラデー タは創作畑の人たちが作っていて、 形式変換などが望めるものではない

Slide 27

Slide 27 text

1. 落ちるキャラデー タがある メモリ関係のエラー で落ちる 任意のキャラデー タを突っ込んで動作させたい……。

Slide 28

Slide 28 text

1. 落ちるキャラデー タがある ( 解決 ) em++ のデフォルトでは最大メモリサイズが固定値だった。 メモリが足りなくなったら自動的に拡張してくれる ‐s ALLOW_MEMORY_GROWTH=1 をつけてコンパイル。 ( 実行速度遅くなるよという警告が出る )

Slide 29

Slide 29 text

2. 複数キャラをたちあげたい 同じ人格 DLL.js を色々 なキャラデー タに適用したい。 しかし→Emscripten はスクリプトをロー ドした時点で、 グロー バ ルの Module とかに色々 入れてそのまま単一インスタンスとして実 行してしまう。

Slide 30

Slide 30 text

2. 複数キャラをたちあげたい ( 解決 ) 関数で囲って new する ‐‐pre‐js em‐pre.js ‐‐post‐js em‐post.js ( どう見ても正攻法ではない気がする…… → 現在は Worker に隔離 ) var Kawari = function(){ // em‐pre.js (****Emscriptenでコンパイルされたコード...****) this['Module'] = Module; this['FS'] = FS; this['PATH'] = PATH; this['ERRNO_CODES'] = ERRNO_CODES; this['NODEFS'] = NODEFS; this['IDBFS'] = IDBFS; this['WORKERFS'] = WORKERFS; }; // em‐post.js var kawari = new Kawari(); console.log(kawari.ERRNO_CODES);

Slide 31

Slide 31 text

3. ファイルシステムの取り扱い ユー ザー が投げる任意のキャラデー タ ( ファイルサイズ無制 限の ZIP) を展開して FS に配置し、 中に入っているスクリプト を動かしたい。 DLL が FS に書き込むセー ブファイル等を保持したい。 追加の前提 ブラウザではロー カルのファイルシステムは読めない。 Worker で IndexedDB にアクセスできないブラウザ (IE) がある。

Slide 32

Slide 32 text

3. ファイルシステムの取り扱い ( 解決 ) npm install browserfs 1. ZIP を展開し (FS API をエミュレー トする )BrowserFS で IndexedDB に保存して保持 2. (IndexedDB は非同期 API しかないので同期 API を使う )Emscripten FS にメモリロー ドしてから DLL 実行 3. 実行終了後に FS の中身を IndexedDB に書き戻す 数 MB の ZIP 複数扱う時点で IndexedDB 以外容量足りません Emscripten 付属の IndexedDB の扱いも大して変わらない めちゃくちゃ泥臭いので何かいい方法ないでしょうかね……

Slide 33

Slide 33 text

3. ファイルシステムの取り扱い ( 願い ) Worker で使える IndexedDB の同期版 API 復活しないかなあ mount みたいに FS の一部だけロー ドできないかなあ IE がサポー ト切れますように ( ♪ )

Slide 34

Slide 34 text

4. Shift̲JIS 文字列を渡す 人格用言語 DLL が 2000 年代初頭製なので SJIS 前提 ユー ザー から投げられるキャラデー タのソー スも SJIS 。 互換性のため文字コー ド変換かましたコンパイルはしたくない。 Emscripten デフォルトの Pointer̲stringify や intArrayFromString は Unicode 前提なのか正しく動かなかった。

Slide 35

Slide 35 text

4. Shift̲JIS 文字列を渡す ( 解決 ) npm install encoding‐japanese var _request = Module.cwrap( // DLLのrequest()関数 'request', 'number', ['number', 'number']); var requestStr = "こんにちは"; // intArrayFromStringではダメだった var unicodeReq = Encoding.stringToCode(requestStr); var sjisReq = Encoding.convert(unicodeReq, 'SJIS', 'UNICODE'); var req = allocString(sjisReq); // 文字列メモリ確保 var len = allocLong(req.size); // 文字列長メモリ確保 var resPtr = _request(req.ptr, len.ptr); // request()! var resHeap = new Uint8Array( // 応答文字列のヒープの参照 Module.HEAPU8.buffer, resPtr, len.heap[0]); // intArrayToStringはOK var sjisResStr = Module.intArrayToString(resHeap); Module._free(len.ptr); Module._free(resPtr); // freeする var sjisRes = Encoding.stringToCode(sjisResStr); var unicodeRes = Encoding.convert(sjisRes, 'UNICODE', 'SJIS'); var response = Encoding.codeToString(unicodeRes);

Slide 36

Slide 36 text

4. Shift̲JIS 文字列を渡す ( 解決 ) 詳しくは https://github.com/Narazaka/nativeshiori ↓ 実際のコー ド

Slide 37

Slide 37 text

5. 人格用言語 DLL から別の DLL を呼ぶ 機能の少ない人格用言語 DLL から別の DLL を呼んで機能を補 完する SAORI というインター フェー ス規格が流通している extern "C" ̲̲declspec(dllexport) HGLOBAL ̲̲cdecl request(HGLOBAL h, long *len); extern "C" ̲̲declspec(dllexport) BOOL ̲̲cdecl load(HGLOBAL h, long len); extern "C" ̲̲declspec(dllexport) BOOL ̲̲cdecl unload(); 任意の DLL(.so) 呼びたい

Slide 38

Slide 38 text

5. 人格用言語 DLL から別の DLL を呼ぶ ( 未解決 ) https://github.com/kripken/emscripten/wiki/Linking 2015 年から対応された模様? ( イカガカ初期開発時の 2014 年当時はうやむやだった) 素人が「 ホー ムペー ジ」 に気軽における程度に簡単な対応にした いが、 まだよく調べていません。

Slide 39

Slide 39 text

( 要件によっては ) コンパイル後の対処が大変 今回の要件 = デスクトップアプリとの互換動作 1. 全部 C++ ではなく、JavaScript で書かれたメインルー チンに任 意個数のコンポー ネント DLL を連携させて動作させる。 2. 任意のスクリプトを言語ランタイムに食わせてデスクトップ と互換の動作・ ファイル操作をする。 3. 入出力は SJIS 。 4. DLL から別の任意 DLL を呼ぶ ( 未解決 ) 。 めぼしい知見がなかったので全部無理矢理解決

Slide 40

Slide 40 text

知見はまだまだ足りない エミュレー ター で動かしているようなものなので C++ や JavaScript 単体と異なった事情が出てくる。 「 全部 C++ で書いてそのまま実行する」 以外のシナリオ例が あまりない。

Slide 41

Slide 41 text

まとめ ブラウザでデスクトップマスコット「 伺か」 を動かしてみた DLL があったので Emscripten で JS にした 要求仕様に沿って DLL を扱うにあたって、 複数起動、 ファイル システム、 文字コー ド、 動的リンクの問題があった この様な ( ニッチな ) 需要にみあう知見は ( 当然 ) 充実していない

Slide 42

Slide 42 text

[PR] イカガカ開発チー ムドリコムはエンジニアを 募集しています!