背景
OpenGLなソースをEmscriptenでJavaScriptに変換できることは分かったのだが、OpenGLなソースだとテクスチャーをファイルとして読み込むようなケースが多々ある、Emscriptenでこういったファイルの読み込みも可能なような記述があるが、具体的な方法が英語力の低さから分からずにいた。
そんな折、はてなの人力検索ですばらしい質問と回答を発見して、これを手がかりにC++でファイルを読み込むプログラムをEmscriptenでJavaScriptに変換することが出来た。
前提
EmscriptenでJavaScriptに変換された本体のプログラムのファイルアクセスは仮想ファイルシステムを介して行われる。
この為、本体のプログラムを実行する前に、この仮想ファイルシステムに必要なファイルやフォルダの登録が必要となる模様。
emscriptenのページでは自動でやってくれるやり方もあるようだが、このやり方だと、ファイルの内容がコンパイル時に埋め込まれてします。(まぁ、別ファイルにできるので、こちらを後から変更できそうだが。。)
C/C++のソース中でファイル名を指定して読んでいる場合、FS.createPreloadedFileを使うと対応できる。
また、前処理内で、動的にデータを作成してしまうAPIも用意されている模様。
対象のファイルはemccを実行するディレクトリを/としてJavaScript側では扱われる模様(絶対パス指定ならそのままのパスで扱われる模様)
同名ファイルでフォルダが違うファイルを読み込むサンプル
C++のソース
#include <fstream> #include <iostream> using namespace std; int main (int argc, char **argv) { string line; ifstream fin ("./input.txt"); while (getline (fin, line)) { cout << line << endl; } fin.close (); fin.open ("data/input.txt"); while (getline (fin, line)) { cout << line << endl; } fin.close (); return 0; }
前処理用のJavaScriptソースの準備
前処理のJavaScriptでやり事は以下
- 仮想ファイルシステムにフォルダを登録
- 仮想ファイルシステムにファイルを登録
前処理用のJavaScript
Module['preRun'] = function () { FS.createFolder( '/', 'data', true, true ); FS.createPreloadedFile( '/', 'input.txt', '/input.txt', // httpでアクセスする際のURLを指定 true, false ); FS.createPreloadedFile( '/data', 'input.txt', '/data/input.txt', // httpでアクセスする際のURLを指定 true, false ); };
--pre-jsを指定してhtmlファイルを作成
emcc target.cpp -o target.html --pre-js pre.js
読み込まれるファイルの用意
echo "hogehoge" > input.txt mkdir data echo "foobar">data/input.txt
HTTPサーバを立てる
pre.jsのFS.createPreloadedFileでXMLHttpRequestを内部的に読んでいるので、ローカルのファイルといえどもWebサーバーを介してのアクセスが必要です。
Emscriptenな環境ではPythonが入っているので、SimpleHTTPServerでさくっとWebサーバーを立ち上げて試せます。
python -m SimpleHTTPServer 8000
ブラウザでアクセスしてみる
emccのコンパイルがうまくいっても安心できません。pre.jsで仮想ファイルとHTTPアクセスされる実ファイルのマッピングが誤っていると、いくら待っても、preloadの表示のままになります。
http://localhost:8000/target.html
まとめ
仮想フォルダを準備するというのにちょっと躓きましたが、思ったより、やってみると簡単だった。人力検索はてなの質問者様、回答者様に感謝です。
以上、ファイルの読み込みのあるCやC++をEmscriptenでJavaScriptに変換する方法でした。
参考資料
- kripken/emscripten
- ファイルを読み込むC言語のプログラムをemscriptenでjavascriptに変換して
- ファイルの扱いが解説されており、勉強になった。
- emscriptenのファイルIO