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.2k
伺か on Browser
デスクトップマスコットをブラウザ移植してみた
利用者視点のEmscriptenとその周辺
Narazaka
October 05, 2016
Tweet
Share
More Decks by Narazaka
See All by Narazaka
UEFIでうごくゲームを作ってみた〜2017年夏休みの自由研究〜
narazaka
0
7.2k
真のrequire()をブラウザで
narazaka
0
1.3k
Excelは殺す絶対にだ
narazaka
0
770
VBAナメてた
narazaka
2
1.9k
Other Decks in Programming
See All in Programming
Semantic Kernelのネイティブプラグインで知識拡張をしてみる
tomokusaba
0
180
rails stats で紐解く ANDPAD のイマを支える技術たち
andpad
1
290
17年周年のWebアプリケーションにTanStack Queryを導入する / Implementing TanStack Query in a 17th Anniversary Web Application
saitolume
0
250
あれやってみてー駆動から成長を加速させる / areyattemite-driven
nashiusagi
1
200
menu基盤チームによるGoogle Cloudの活用事例~Application Integration, Cloud Tasks編~
yoshifumi_ishikura
0
110
短期間での新規プロダクト開発における「コスパの良い」Goのテスト戦略」 / kamakura.go
n3xem
2
170
Haze - Real time background blurring
chrisbanes
1
510
なまけものオバケたち -PHP 8.4 に入った新機能の紹介-
tanakahisateru
1
120
RWC 2024 DICOM & ISO/IEC 2022
m_seki
0
210
[JAWS-UG横浜 #76] イケてるアップデートを宇宙いち早く紹介するよ!
maroon1st
0
460
「Chatwork」Android版アプリを 支える単体テストの現在
okuzawats
0
180
LLM Supervised Fine-tuningの理論と実践
datanalyticslabo
3
1.1k
Featured
See All Featured
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
Building Applications with DynamoDB
mza
91
6.1k
A Modern Web Designer's Workflow
chriscoyier
693
190k
Documentation Writing (for coders)
carmenintech
66
4.5k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
2
170
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
44
9.3k
Git: the NoSQL Database
bkeepers
PRO
427
64k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7k
Testing 201, or: Great Expectations
jmmastey
40
7.1k
Building Your Own Lightsaber
phodgson
103
6.1k
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] イカガカ開発チー ムドリコムはエンジニアを 募集しています!