mcpField
W
wasm-emscripten

wasm-emscripten

github.com/mohitmishra786開発269524 回インストール18 週間前に更新
リポジトリ

wasm-emscripten について

Emscripten で C/C++ を WebAssembly にコンパイルするエージェント向けスキルです。ブラウザーと WASI のターゲットを扱い、関数のエクスポート、メモリ設定、Asyncify、最適化、デバッグを説明します。

主な機能

  1. 01emcc のビルドフラグ選択
  2. 02C 関数の JavaScript へのエクスポート
  3. 03リニアメモリとスタックの設定
  4. 04Asyncify による非同期処理
  5. 05WASM の最適化とデバッグ
  6. 06ブラウザーと WASI ターゲットの区別

活用シーン

  1. 01C/C++ プログラムの WebAssembly 化
  2. 02JavaScript からエクスポート済み C 関数を呼び出す
  3. 03非同期環境向けに同期 C コードを適応
  4. 04WASM のメモリや実行時問題の調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill wasm-emscripten

インストール後、Claude Code で/wasm-emscriptenを入力して読み込まれたか確認します。

同梱ファイルreferences/emscripten-linker-flags.md

詳細

Emscripten を使った WebAssembly

目的

Emscripten を使って C/C++ を WebAssembly にコンパイルする方法をエージェントに案内します。emcc のフラグ選択、関数のエクスポート、メモリモデルの設定、非同期な C コードを実現する Asyncify、WASM バイナリのデバッグ、WASI とブラウザー向けターゲットの使い分けを扱います。

トリガー

  • 「Emscripten を使って C を WebAssembly にコンパイルするにはどうすればよいですか?」
  • 「C の関数を JavaScript にエクスポートするにはどうすればよいですか?」
  • 「Emscripten では WebAssembly のメモリはどのように機能しますか?」
  • 「.wasm ファイルをデバッグするにはどうすればよいですか?」
  • 「Asyncify を使って同期的な C コードを非同期にするにはどうすればよいですか?」
  • 「WASI と Emscripten のブラウザー向けターゲットの違いは何ですか?」

ワークフロー

1. セットアップと最初のビルド
# Install Emscripten SDK
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh    # add emcc to PATH

# Verify
emcc --version

# Compile C to WASM (browser target)
emcc hello.c -o hello.html          # generates hello.html + hello.js + hello.wasm
emcc hello.c -o hello.js            # just JS + WASM (no HTML shell)

# Serve locally (WASM requires HTTP, not file://)
python3 -m http.server 8080
# Open: http://localhost:8080/hello.html
2. 関数を JavaScript にエクスポートする
// math.c
#include <emscripten.h>

// EMSCRIPTEN_KEEPALIVE prevents dead-code elimination
EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
    return a + b;
}

EMSCRIPTEN_KEEPALIVE
double sqrt_approx(double x) {
    return x * 0.5 + 1.0;
}
# Export specific functions
emcc math.c -o math.js \
  -s EXPORTED_FUNCTIONS='["_add","_sqrt_approx"]' \
  -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' \
  -s MODULARIZE=1 \
  -s EXPORT_NAME=MathModule

# The leading underscore is required for C functions
// Using exported functions in JS
const Module = await MathModule();

// Direct call
const result = Module._add(3, 4);

// Via ccall (type-safe)
const result2 = Module.ccall('add', 'number', ['number', 'number'], [3, 4]);

// Via cwrap (creates a callable JS function)
const add = Module.cwrap('add', 'number', ['number', 'number']);
console.log(add(3, 4));  // 7
3. メモリモデル

Emscripten は、C と JS の両方からアクセスできる線形メモリヒープを提供します。

# Configure initial and maximum heap
emcc prog.c -o prog.js \
  -s INITIAL_MEMORY=16MB \
  -s MAXIMUM_MEMORY=256MB \
  -s ALLOW_MEMORY_GROWTH=1    # allow dynamic growth

# Stack size (default 64KB)
emcc prog.c -o prog.js -s STACK_SIZE=1MB

# Shared memory (for SharedArrayBuffer / threads)
emcc prog.c -o prog.js -s SHARED_MEMORY=1 -s USE_PTHREADS=1
// Accessing C memory from JS
const ptr = Module._malloc(1024);     // allocate
Module.HEAPU8.set([1, 2, 3], ptr);   // write bytes
Module._free(ptr);                     // free

// Read a C string
const strPtr = Module.ccall('get_message', 'number', [], []);
const str = Module.UTF8ToString(strPtr);

// Write a string to C
const jsStr = "hello";
const cStr = Module.stringToNewUTF8(jsStr);  // malloc + copy
Module._process_string(cStr);
Module._free(cStr);
4. Asyncify — 非同期環境で同期的な C を使う

Asyncify を使うと、同期的な C コードを一時停止して再開し、非同期操作(fetch()、スリープなど)を実行できます。

// async.c
#include <emscripten.h>

// Synchronous sleep in C (blocks C, but yields to JS event loop)
EM_JS(void, do_fetch, (const char *url), {
    // Emscripten generates wrappers to suspend C while JS runs
    Asyncify.handleAsync(async () => {
        const resp = await fetch(UTF8ToString(url));
        const text = await resp.text();
        console.log(text);
    });
});

void process_url(const char *url) {
    do_fetch(url);     // looks synchronous in C
    printf("fetch complete\n");
}
# Enable Asyncify
emcc async.c -o async.js \
  -s ASYNCIFY \
  -s ASYNCIFY_STACK_SIZE=16384 \
  -O2   # Asyncify works better with optimization
5. 最適化と wasm-opt
# Optimization levels
emcc prog.c -O0 -o prog.js    # no optimization (fastest build)
emcc prog.c -O2 -o prog.js    # balanced
emcc prog.c -O3 -o prog.js    # aggressive
emcc prog.c -Os -o prog.js    # optimize for size
emcc prog.c -Oz -o prog.js    # aggressive size (Emscripten's smallest)

# Post-process with wasm-opt (Binaryen)
wasm-opt -Oz -o prog.opt.wasm prog.wasm    # optimize for size
wasm-opt -O4 -o prog.opt.wasm prog.wasm    # optimize for speed

# Compare sizes
ls -lh prog.wasm prog.opt.wasm
6. WASM のデバッグ
# Build with debug info
emcc prog.c -g -O0 -o prog.html \
  -s ASSERTIONS=1 \
  -s SAFE_HEAP=1      # catch misaligned accesses

# In Chrome DevTools:
# Sources → prog.wasm → line-by-line C source debugging
# (requires -g and browser with WASM debugging support)

# LLDB with WASM (wasmtime)
# See skills/runtimes/wasm-wasmtime for CLI WASM debugging
# Emscripten debug helpers
emcc prog.c -o prog.js \
  -s ASSERTIONS=2       # extensive runtime checks
  -s SAFE_HEAP=1        # sanitize heap accesses
  -s STACK_OVERFLOW_CHECK=1

# Print generated JS
emcc prog.c -o prog.js && cat prog.js | head -100
7. WASI とブラウザー向けターゲット
機能ブラウザー(Emscripten)WASI
ホスト APIWeb API(fetch、WebGL など)POSIX のサブセット(ファイル、stdin/stdout)
ランタイムブラウザーの JS エンジンwasmtime、wasmer、WAMR、Node.js
スレッドSharedArrayBuffer + pthreadswasi-threads(制限あり)
ネットワークfetch()、WebSocketwasi-http(preview2)
用途Web アプリケーションサーバーサイド、CLI ツール、エッジ
# Build for WASI (no browser JS, pure WASM)
emcc prog.c -o prog.wasm --target=wasi

# Or use wasi-sdk (better WASI support than Emscripten)
/opt/wasi-sdk/bin/clang --sysroot=/opt/wasi-sdk/share/wasi-sysroot \
  prog.c -o prog.wasm
wasmtime prog.wasm

Emscripten のリンカーフラグについては、references/emscripten-linker-flags.md を参照してください。

関連スキル

  • wasmtime CLI と Rust の組み込みによるサーバーサイド WASM には、skills/runtimes/wasm-wasmtime を使用してください
  • WASI SDK を使った Clang ベースの WASM コンパイルには、skills/compilers/clang を使用してください
  • WASM バイナリ構造の調査には、skills/binaries/elf-inspection を使用してください

コメント