Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
伺か on Browser
Search
Narazaka
October 05, 2016
Programming
0
1.1k
伺か on Browser
デスクトップマスコットをブラウザ移植してみた
利用者視点のEmscriptenとその周辺
Narazaka
October 05, 2016
Tweet
Share
More Decks by Narazaka
See All by Narazaka
UEFIでうごくゲームを作ってみた〜2017年夏休みの自由研究〜
narazaka
0
6.8k
真のrequire()をブラウザで
narazaka
0
1.2k
Excelは殺す絶対にだ
narazaka
0
700
VBAナメてた
narazaka
2
1.8k
Other Decks in Programming
See All in Programming
APIのない大学ログインWebサービスをWKWebViewとJavaScriptでアプリ化した話
akidon0000
1
330
feature環境をGitHub ActionsとCloudFormationでいい感じに管理する
nealle
2
310
英語
s_shimotori
1
220
CSC307 Lecture 09
javiergs
PRO
1
500
CSC307 Lecture 05
javiergs
PRO
0
210
AWS初心者ってどうやってAWSを学ぶ?〜アプリエンジニアがやってよかったアーキテクチャ学習方法〜
yamanashi_ren01
0
190
CSC307 Lecture 08
javiergs
PRO
0
330
初心者がおさえておきたいAWS CDKのベストプラクティス 2024
konokenj
15
7.3k
[After Kotlin Fest 2024 LT Night @ Sansan] もっともっとKotlinを好きになる!K2 Compiler Pluginで遊んでみよう!
kitakkun
2
260
ドメイン駆動設計の実践
masuda220
PRO
17
5.1k
Findy - エンジニア向け会社紹介 / Findy Letter for Engineers
findyinc
2
81k
わかりやすい正解を捨てて、コトに向き合う - スクラムフェス金沢2024 スポンサーセッション
yusukekokubo
0
170
Featured
See All Featured
Faster Mobile Websites
deanohume
303
30k
Building a Scalable Design System with Sketch
lauravandoore
458
32k
10 Git Anti Patterns You Should be Aware of
lemiorhan
652
58k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
155
14k
Code Review Best Practice
trishagee
58
16k
Creatively Recalculating Your Daily Design Routine
revolveconf
214
11k
Principles of Awesome APIs and How to Build Them.
keavy
124
16k
The Art of Programming - Codeland 2020
erikaheidi
48
13k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
26
1.8k
Imperfection Machines: The Place of Print at Facebook
scottboms
262
13k
Code Reviewing Like a Champion
maltzj
517
39k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
189
16k
Transcript
うかがか 伺か on Browser デスクトップマスコットをブラウザ移植してみた 利用者視点の Emscripten とその周辺
自己紹介 佐藤隆人 ( な ら ざ か 奈良阪 ) Twitter:
@narazaka Github: @Narazaka npm: @narazaka CPAN: NARAZAKA ドリコム 2015 新卒 (2 年目 ) サー バー サイド Ruby 書いてます Perl / JavaScript / Ruby / C# あたりが好き その他 : 伺か / 漫画読み描き / OP アニメ愛好家 / 鉄
※ 注意 1 から 10 まで趣味の話です プロダクションレベルの知見ではありません。 試行錯誤の途中なのでアドバイスなどいただけると幸いです。
近年やってる趣味
うかがか 伺か 2000 年頃に一部で流行ったデスクトップマスコット
デスクトップマスコットのなかま? たち ポストペット ペルソナウェア デスクトップのメイドさん いもうとデスクトップ まいんど・ ふぉ~ かす お座りマルチ
かわいい
かわいい
懐かしい
懐かしい
なんかすごい
キャラクター 表現プラットフォー ム 16 年目の現在もたくさんのキャラの更新がある
しかし…… 世はスマホ全盛
「 キャラクター の居場所 デスクトップ」 の消滅
…… スマホでも使いたい ブラウザにのせて動かせないか?
「 伺か on Browser イカガカ」 プロジェクト コー ド https://github.com/Ikagaka デモ
http://ikagaka.github.io/Ikagaka.demo/
ブラウザに載せるにあたって…… うかがか 伺か はどういうプログラム?
うかがか 伺か (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) がいくつか存在
各人格記述用言語 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!" }
_ 人人人人人人人_ > Emscripten <  ̄Y^Y^Y^Y^Y^Y  ̄
Linux で依存なくコンパイルできる C++ だった ( 一部 boost はずした ) 既存のコー
ドほぼ変更なし
Makefile もフラグ追加と g++ ‑> em++ rem emsdk1.25.0 on Windows emcmdprompt.bat
D: cd kawari make
各人格記述用言語 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
_ 人人人人人人人_ > Emscripten <  ̄Y^Y^Y^Y^Y^Y  ̄ ‑ 完 ‑
! ここからが問題 ! ~Emscripten とその周辺~
今回の最重要要件 = 互換動作 キャラデー タの変更なしに デスクトップと同じ挙動を保証したい キャラデー タは創作畑の人たちが作っていて、 形式変換などが望めるものではない
1. 落ちるキャラデー タがある メモリ関係のエラー で落ちる 任意のキャラデー タを突っ込んで動作させたい……。
1. 落ちるキャラデー タがある ( 解決 ) em++ のデフォルトでは最大メモリサイズが固定値だった。 メモリが足りなくなったら自動的に拡張してくれる ‐s
ALLOW_MEMORY_GROWTH=1 をつけてコンパイル。 ( 実行速度遅くなるよという警告が出る )
2. 複数キャラをたちあげたい 同じ人格 DLL.js を色々 なキャラデー タに適用したい。 しかし→Emscripten はスクリプトをロー ドした時点で、
グロー バ ルの Module とかに色々 入れてそのまま単一インスタンスとして実 行してしまう。
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);
3. ファイルシステムの取り扱い ユー ザー が投げる任意のキャラデー タ ( ファイルサイズ無制 限の ZIP)
を展開して FS に配置し、 中に入っているスクリプト を動かしたい。 DLL が FS に書き込むセー ブファイル等を保持したい。 追加の前提 ブラウザではロー カルのファイルシステムは読めない。 Worker で IndexedDB にアクセスできないブラウザ (IE) がある。
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 の扱いも大して変わらない めちゃくちゃ泥臭いので何かいい方法ないでしょうかね……
3. ファイルシステムの取り扱い ( 願い ) Worker で使える IndexedDB の同期版 API
復活しないかなあ mount みたいに FS の一部だけロー ドできないかなあ IE がサポー ト切れますように ( ♪ )
4. Shift̲JIS 文字列を渡す 人格用言語 DLL が 2000 年代初頭製なので SJIS 前提
ユー ザー から投げられるキャラデー タのソー スも SJIS 。 互換性のため文字コー ド変換かましたコンパイルはしたくない。 Emscripten デフォルトの Pointer̲stringify や intArrayFromString は Unicode 前提なのか正しく動かなかった。
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);
4. Shift̲JIS 文字列を渡す ( 解決 ) 詳しくは https://github.com/Narazaka/nativeshiori ↓ 実際のコー
ド
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) 呼びたい
5. 人格用言語 DLL から別の DLL を呼ぶ ( 未解決 ) https://github.com/kripken/emscripten/wiki/Linking
2015 年から対応された模様? ( イカガカ初期開発時の 2014 年当時はうやむやだった) 素人が「 ホー ムペー ジ」 に気軽における程度に簡単な対応にした いが、 まだよく調べていません。
( 要件によっては ) コンパイル後の対処が大変 今回の要件 = デスクトップアプリとの互換動作 1. 全部 C++
ではなく、JavaScript で書かれたメインルー チンに任 意個数のコンポー ネント DLL を連携させて動作させる。 2. 任意のスクリプトを言語ランタイムに食わせてデスクトップ と互換の動作・ ファイル操作をする。 3. 入出力は SJIS 。 4. DLL から別の任意 DLL を呼ぶ ( 未解決 ) 。 めぼしい知見がなかったので全部無理矢理解決
知見はまだまだ足りない エミュレー ター で動かしているようなものなので C++ や JavaScript 単体と異なった事情が出てくる。 「 全部
C++ で書いてそのまま実行する」 以外のシナリオ例が あまりない。
まとめ ブラウザでデスクトップマスコット「 伺か」 を動かしてみた DLL があったので Emscripten で JS にした
要求仕様に沿って DLL を扱うにあたって、 複数起動、 ファイル システム、 文字コー ド、 動的リンクの問題があった この様な ( ニッチな ) 需要にみあう知見は ( 当然 ) 充実していない
[PR] イカガカ開発チー ムドリコムはエンジニアを 募集しています!