SlideShare a Scribd company logo
1 of 34
Download to read offline
emscriptenでC/C++プログラムを
webブラウザから使うまでの
難所攻略
伊藤 祐司
2015/6/20 Creators MeetUp #29
自己紹介
伊藤 祐司
バックエンドの設計 開発
フレームワークの作成 バイナリ・テキスト変換 クローラー
アルゴリズム 仮想マシン
下北沢OSSカフェでPROCESS WARPというシステムを作っています
http://www.processwarp.org/
GitHub llamerada-jp
facebook ito.yuuji
blog http://llamerad-jp.hatenablog.com/
背景・動機
PROCESS WARP
複数のマシンを接続し、プロセス転送(ライブマイ
グレーション)機能を持ったアプリ実行基盤
webブラウザ、Linux、Unix上で専用VMを実行
背景・動機
PROCESS WARPのコアプログラムをweb上でも動かして手
軽に使ってもらいたいけど開発に時間は掛けたくない
CORE
SOURCE
(C++)
C/C++
compiler
emscripten
実際にやる前に
インストールからハローワールド
HTML側のカスタマイズ
JavaScriptとC/C++の連携
ポインタと文字列
http://emscripten.org/
C/C++からJavaScriptへのコンパイル(コンバート)を行
うアプリケーション
C/C++のコードをLLVM IR経由でJavaScriptへ変換
標準C/C++ライブラリ, POSIX, SDL, OpenGLが使える
C/C++でブラウザアプリケーションが作れる!
Alon Zakai
(kripken)
LLVM
http://llvm.org/
コンパイラ基盤、コンパイラの共通機能(最適化など)をパッケージ
化したもの
clang C/C++/Objective-C/swiftコンパイラ
LLILC .netからの変換 by Microsoft
https://github.com/dotnet/llilc
その他、gnuコンパイラをフロントエンドとし多数の言語を処理可能
Fortran, Ada, Go
http://dragonegg.llvm.org
開発が非常に活発
Chris Lattner
コンパイルの流れ
LLVM
Optimizer
Clang
dragon
egg
original
frontend
C/C++
Obj-C
Swift
Fortran
Ada
Go
original
language
-emit-llvm
x86
backend
ARM
backend
iPhone
Android
Raspberry Pi
PC
objectfile
for
LLVMとemscripten
LLVM
Optimizer
Clang
C/C++
emscripten
JavaScript!
できないこと
マルチスレッド
ソケット通信
アセンブラ
他、JavaScriptでできないこと
主要モダンブラウザではだいたい動くけどそれぞれ制
限事項(特にIE)がある
http://kripken.github.io/emscripten-site/docs/
porting/guidelines/browser_limitations.html
実際にやる前に
インストールからハローワールド
HTML側のカスタマイズ
JavaScriptとC/C++の連携
ポインタと文字列
インストール方法
LinuxやOSXではPortable SDKを使うのが一番良い
renv, nodebrewのように複数バージョンを依存アプリ
(clang, node.js)込みでよしなに管理してくれる
https://kripken.github.io/emscripten-site/docs/
getting_started/downloads.html
$ tar vzxf emsdk-protable.tar.gz
$ cd emsdk_portable
$ ./emsdk install latest
$ ./emsdk activate latest
$ source emsdk_env.sh
実行前に環境変数を設定
デフォルトのコンパイラがemsdk
のインストールしたclangになる
console
Hello world
// emscriptenのヘッダファイル
#include <emscripten.h>
int main(int argc, char* argv[]) {
printf("hello world.”);
return 0;
}
hello.c
$ emcc hello.c -o hello.html console
hello.html hello.js
こんにちわ
実際にやる前に
インストールからハローワールド
HTML側のカスタマイズ
JavaScriptとC/C++の連携
ポインタと文字列
こんにちわ
見た目を変える
emsdk/emscripten/<バージョン>/src/
shell_minimal.html をもとにHTMLをカスタム
$ emcc hello.c --shell-file custom.html -o
hello.html
console
見た目を変える
#canvas
OpenGLを使わないなら消してし
まって構わない
#output
Module.printからテキストが出力
されている
他もJavaScript部分と整合性を取
りながら変更してOK
{{ SCRIPT }}がscriptタグに変換
される
HTMLの生成をやめる
デザイン変更のたびにコンパイルするのは面倒
<script async type="text/javascript"
src="hello.js">とModuleがあればHTMLは直接
編集したい
$ emcc hello.c -o hello.js
console
hello.js
実際にやる前に
インストールからハローワールド
HTML側のカスタマイズ
JavaScriptとC/C++の連携
ポインタと文字列
ループを作る
main内で無限ループを回すとブラウザへ処理が戻らない
普通のJavaScriptであればsetTimeout
emscripten_set_main_loop(<関数>, <FPS>, true);を利用
#include <emscripten.h>
void main_loop() {
// メイン処理をココに
}
int main(int argc, char* argv[]) {
// 初期化処理とか
// メインループを登録
emscripten_set_main_loop(main_loop, 0, true);
return 0;
}
C/C++
emscriptenとネイティブ
でコードを切り替える
#include <emscripten.h>
void main_loop() {
// メイン処理をココに
}
int main(int argc, char* argv[]) {
// 初期化処理とか
#ifdef EMSCRIPTEN
// メインループを登録
emscripten_set_main_loop(main_loop, 0, true);
#else
// メインループを呼び出し
while(true) main_loop();
#endif
return 0;
}
C/C++
emscriptenでコンパイルする場合、EMSCRIPTENが
定義される
C/C++からJavaScriptを
呼び出す
インラインアセンブラはJavaScriptとして実行される
(固定機能)
void emscripten_run_script(<JavaScript>);で渡した
文字列をJavaScriptとして実行
JavaScriptのeval();のような動作
int emscripten_run_script_int();
std::string emscripten_run_script_string();
int r = emscripten_run_script_int("screen.width");
C/C++
JavaScriptから
C/C++関数を呼び出す
embind機能でJavaScriptから呼び出す関数を指定しておく
引数、戻り値は変換される(※構造体はNG)
https://kripken.github.io/emscripten-site/docs/
porting/connecting_cpp_and_javascript/
embind.html#built-in-type-conversions
#include <math.h>
#include <emscripten.h>
#include <emscripten/bind.h> // ヘッダ
using namespace emscripten; // 名前空間
double _pow(double a, int b) {
return pow(a, b);
}
EMSCRIPTEN_BINDINGS(mod) {
function("c_pow", &_pow); // Module.c_pow();
}
sample.cpp
JavaScriptから
C/C++関数を呼び出す
sample.jsが読み込まれた後から利用可能になるので、
onloadの中などでは利用できない
コンパイルオプションに-s EXPORT_ALL=1を指定すると
全ての関数がexportされるがjsファイルが巨大になる
$ em++ sample.cpp --bind -o sample.js
console
var p = Module.c_pow(3.14, 2);
JavaScript
Makefileの利用
emcmake, emconfigure, emmakeを利用すると、普通のアプリ
ケーションをemscriptenでコンパイルできる
未対応のライブラリに依存していたりすると上手く動かない
CC, CXX, 他の環境変数などをemscripten用に書き換えている
$ ememake cmake .
$ emconfigure configure
$ emmake make
console
実際にやる前に
インストールからハローワールド
HTML側のカスタマイズ
JavaScriptとC/C++の連携
ポインタと文字列
int value1 = 1192; // 0x04a8
short value2 = 758; // 0x02f6
char value3 = -1; // 0xff
char value4 = 99; // 0x63
メモリ空間
emscriptenでは、C/C++の変数をArrayBufferで作った擬似
的なメモリ空間に保存している
Module.HEAPU8などDataViewでアクセスできる
ビッグエンディアン
C/C++
00 00 04 a8 02 f6 ff 63
Memory
…… … …
ポインタ
ポインタ = 先頭からのインデックスと考えればOK
ポインタはembindで変換されないのでunsigned intにキャスト
int value1 = 1192; // 0x04a8
short value2 = 758; // 0x02f6
char value3 = -1; // 0xff
char value4 = 99; // 0x63
return (unsigned int)(&value1); // unsigned int getptr();
C/C++
a8 04 00 00 f6 02 ff 63
JavaScriptfor (int i = 0; i < 8; i ++) {
console.log(Module.HEAPU8[Module.getptr() + i]);
}
…… … …
for (int i = 0; i < 2; i ++) {
console.log(Module.HEAPU32[Module.getptr() / 4 + i]);
}
for (int i = 0; i < 4; i ++) {
console.log(Module.HEAPU16[Module.getptr() / 2 + i]);
}
intやshortでアクセス
000004a8 63ff02f6
JavaScript
… …
04a8 0000 02f6 63ff
JavaScript
… …
a8 04 00 00 f6 02 ff 63…… … …
もっと簡単にポインタ
Module.getValue(<ポインタ>, <型>);
Module.setValue(<ポインタ>, <値>, <型>);
JavaScript
var v = Module.getValue(Module.getptr(), 'i32');
Module.setValue(Module.getptr(), v + 1, 'i32');
console.log(Pointer_stringify(Module.getptr()));
文字列
C/C++からJavaScriptで文字列を授受するときはポインタを使う場合が
多い
Pointer_stringify(<ポインタ>[, <長さ>]);を使って文字列を取り出す
JavaScriptからC/C++へ文字列を渡す場合、引数の型をstd::stringにし
ておくとemscriptenで変換される
unsigned int getptr() {
char* str = "hello world!";
return (unsigned int)(&str);
}
C/C++
JavaScript
まとめ
基本的なC/C++とJavaScript連携はだいたいできる
OpenGLや、Moduleを使ったさらなる制御もできる
できることと、できないことが分かった?
ポインタはタダのインデックス
アルゴリズムやコアは共有できてもGUI部分は別々の実
装のほうが良いと思う
C/C++からDOMを操作するライブラリとかあったらど
うなんでしょうね?
Moduleの中を覗いてみると凄い作りだったり…
以上
ありがとうございました

More Related Content

What's hot

Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
Genya Murakami
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
Norishige Fukushima
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
Moriharu Ohzu
 

What's hot (20)

WebAssemblyのWeb以外のことぜんぶ話す
WebAssemblyのWeb以外のことぜんぶ話すWebAssemblyのWeb以外のことぜんぶ話す
WebAssemblyのWeb以外のことぜんぶ話す
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
 
【Unite Tokyo 2018】誘導ミサイル完全マスター
【Unite Tokyo 2018】誘導ミサイル完全マスター【Unite Tokyo 2018】誘導ミサイル完全マスター
【Unite Tokyo 2018】誘導ミサイル完全マスター
 
C++のライブラリを簡単に眺めてみよう
C++のライブラリを簡単に眺めてみようC++のライブラリを簡単に眺めてみよう
C++のライブラリを簡単に眺めてみよう
 
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説
 
代数的実数とCADの実装紹介
代数的実数とCADの実装紹介代数的実数とCADの実装紹介
代数的実数とCADの実装紹介
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるな
 
なぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリングなぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリング
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
Rustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったかRustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったか
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 
C++20 モジュールの概要 / Introduction to C++ modules (part 1)
C++20 モジュールの概要 / Introduction to C++ modules (part 1)C++20 モジュールの概要 / Introduction to C++ modules (part 1)
C++20 モジュールの概要 / Introduction to C++ modules (part 1)
 
Wiresharkの解析プラグインを作る ssmjp 201409
Wiresharkの解析プラグインを作る ssmjp 201409Wiresharkの解析プラグインを作る ssmjp 201409
Wiresharkの解析プラグインを作る ssmjp 201409
 
【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計
【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計
【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計
 
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
 
Unicode文字列処理
Unicode文字列処理Unicode文字列処理
Unicode文字列処理
 

Similar to emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略

Power shell で DSL
Power shell で DSLPower shell で DSL
Power shell で DSL
urasandesu
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniter
Masanori Oobayashi
 
13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs
Takayoshi Tanaka
 

Similar to emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略 (20)

【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門
 
Power shell で DSL
Power shell で DSLPower shell で DSL
Power shell で DSL
 
FPGAアクセラレータの作り方 (IBM POWER+CAPI編)
FPGAアクセラレータの作り方 (IBM POWER+CAPI編)FPGAアクセラレータの作り方 (IBM POWER+CAPI編)
FPGAアクセラレータの作り方 (IBM POWER+CAPI編)
 
Node.js勉強会 Framework Koa
Node.js勉強会 Framework KoaNode.js勉強会 Framework Koa
Node.js勉強会 Framework Koa
 
Docker講習会資料
Docker講習会資料Docker講習会資料
Docker講習会資料
 
Windows Azure PHP Tips
Windows Azure PHP Tips Windows Azure PHP Tips
Windows Azure PHP Tips
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniter
 
Adaptive optimization of JIT compiler
Adaptive optimization of JIT compilerAdaptive optimization of JIT compiler
Adaptive optimization of JIT compiler
 
13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs
 
CMake multiplatform build-tool
CMake multiplatform build-toolCMake multiplatform build-tool
CMake multiplatform build-tool
 
PEZY-SC programming overview
PEZY-SC programming overviewPEZY-SC programming overview
PEZY-SC programming overview
 
Clrh 20140906 lt
Clrh 20140906 ltClrh 20140906 lt
Clrh 20140906 lt
 
Alt#0x008 2017/5/20
Alt#0x008 2017/5/20Alt#0x008 2017/5/20
Alt#0x008 2017/5/20
 
Lxc on cloud
Lxc on cloudLxc on cloud
Lxc on cloud
 
Apache Module
Apache ModuleApache Module
Apache Module
 
Machine configoperatorのちょっとイイかもしれない話
Machine configoperatorのちょっとイイかもしれない話 Machine configoperatorのちょっとイイかもしれない話
Machine configoperatorのちょっとイイかもしれない話
 
NanoA
NanoANanoA
NanoA
 
社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)
 
Buffer overflow
Buffer overflowBuffer overflow
Buffer overflow
 
今だからこそ知りたい Docker Compose/Swarm 入門
今だからこそ知りたい Docker Compose/Swarm 入門今だからこそ知りたい Docker Compose/Swarm 入門
今だからこそ知りたい Docker Compose/Swarm 入門
 

More from 祐司 伊藤

More from 祐司 伊藤 (11)

Container Storage Interface のすべて
Container Storage Interface のすべてContainer Storage Interface のすべて
Container Storage Interface のすべて
 
C/C++とWebAssemblyを利用したライブラリ開発
C/C++とWebAssemblyを利用したライブラリ開発C/C++とWebAssemblyを利用したライブラリ開発
C/C++とWebAssemblyを利用したライブラリ開発
 
C++からWebRTC (DataChannel)を利用する
C++からWebRTC (DataChannel)を利用するC++からWebRTC (DataChannel)を利用する
C++からWebRTC (DataChannel)を利用する
 
詳説WebAssembly
詳説WebAssembly詳説WebAssembly
詳説WebAssembly
 
シンプル Processing !
シンプル Processing !シンプル Processing !
シンプル Processing !
 
PROCESS WARP「プロセスがデバイス間で移動する」仕組みを作る
PROCESS WARP「プロセスがデバイス間で移動する」仕組みを作るPROCESS WARP「プロセスがデバイス間で移動する」仕組みを作る
PROCESS WARP「プロセスがデバイス間で移動する」仕組みを作る
 
PROCESS WARP
PROCESS WARPPROCESS WARP
PROCESS WARP
 
Webブラウザで使えるいろんな処理系
Webブラウザで使えるいろんな処理系Webブラウザで使えるいろんな処理系
Webブラウザで使えるいろんな処理系
 
PROCESS WARP
PROCESS WARPPROCESS WARP
PROCESS WARP
 
PIAXで作る P2Pネットワーク
PIAXで作る P2PネットワークPIAXで作る P2Pネットワーク
PIAXで作る P2Pネットワーク
 
新しい分散実行の仕組み PROCESS WARPについて
新しい分散実行の仕組み PROCESS WARPについて新しい分散実行の仕組み PROCESS WARPについて
新しい分散実行の仕組み PROCESS WARPについて
 

emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略