既存のC/C++ライブラリをWebAssemblyにコンパイルしてブラウザでも活用する方法

---
## はじめに

最近、ブラウザ上でネイティブ級の高速処理を実現できる技術として**WebAssembly（Wasm）**が注目を集めています。私は、電子回路シミュレータの内部構造に興味があり、そこで使える数値線形代数ライブラリ（例：**KLU**）や、常微分方程式ソルバを含む**SUNDIALS**のような**C/C++で書かれた数値計算ライブラリ**をWebAssemblyでも動かしてみたいと考えています。

本記事では、こうした**既存のC/C++ライブラリをWasmにコンパイルして利用する際のメリットや注意点**を解説します。数値計算だけでなく、画像処理、機械学習、暗号など広くC/C++ライブラリを再利用したい方の参考になれば幸いです。

---

## 1. なぜC/C++ライブラリはWasmにコンパイルしやすい、と言われるのか？

### 1.1 LLVMベースのツールチェーンが充実
- WebAssemblyはLLVMをバックエンドとしており、**Emscripten**や**Clang**のWebAssemblyターゲットが整備されています。  
- **Emscripten**: 代表的なツールチェーン。`emcc`コマンドでC/C++→Wasmコンパイルが可能。  
- **Clang/LLVM**: `-target wasm32-unknown-emscripten`などで直接Wasmバイナリを生成できるオプションもあります。

### 1.2 C/C++の移植性の高さ
- C/C++はもともとWindows、Linux、macOS、組込みなどマルチプラットフォーム対応の歴史があり、OS非依存コードを中心とするライブラリが多いです。  
- POSIX関数や標準Cライブラリを使う程度なら、**大きな修正なしでビルドが通る**ケースが多い。  
- Emscriptenには**ファイルシステムエミュレーション**や**スレッドサポート**等もあり、ある程度のOS機能を擬似的に再現できます。

### 1.3 豊富な既存ライブラリ資産
- C/C++には**画像処理（libpng, libjpeg）、音声/動画、暗号、機械学習**などの成熟ライブラリが多数存在します。  
- これらをWebAssemblyにコンパイルすることで、**一からWeb用に書き直す手間を大幅に省き**、JavaScript（やTypeScript）から呼び出して高性能な処理を利用できます。

### 1.4 JavaScriptとのブリッジ（FFI）が容易
- Emscriptenの`cwrap`や`ccall`、`EM_JS`マクロなどで、C/C++関数とJavaScriptを簡単に相互呼び出しできます。  
- Web API（WebGL、Audioなど）との連携用のラッパーコードもある程度整備されているため、フロントエンドでリッチな機能を実装しやすいです。

---

## 2. できない／難しいケースはどんなとき？

### 2.1 OS依存やハードウェアアクセスが強い場合
- デバイスドライバやカーネル機能を直接呼び出すコードは、ブラウザ上では実行不可能。  
- OpenGLやDirectXのようなネイティブAPI依存部はWebGLやWebGPU等へ置き換えが必要な場合があります。

### 2.2 プラットフォーム固有APIの多用
- WindowsのWin32 API、Linux専用のシステムコール、macOSのCocoaフレームワークなどに強く依存するライブラリは移植困難。  
- Emscriptenには対応APIがない場合が多いので、stub（ダミー）を作るか実装を切り離す必要があります。

### 2.3 並列化や高度な並行処理
- WebAssemblyのスレッド対応は近年進化中ですが、MPIのようなプロセス間通信モデルには未対応。  
- OpenMPを多用するコードはEmscriptenオプションとブラウザのSharedArrayBufferサポート次第で制限があります。

### 2.4 大規模ライブラリの依存関係
- BLAS/LAPACKなど下層の数値ライブラリすべてをWasmでビルドし直す必要がある場合も。  
- GUIツールキットや外部プロセス呼び出しなど、Web上で再現困難な部分は機能を削減するしかありません。

### 2.5 セキュリティやライセンス上の問題
- ソースコードやバイナリをWeb公開できないライセンス形態だと移植自体が難しい。  
- Web配布すると、逆アセンブルや改変リスクがある点にも留意が必要です。

---

## 3. 実例：KLUやSUNDIALSなどの数値計算ライブラリ(自分が使いたい)

### 3.1 KLU（Sparse LU分解ライブラリ）
- **SuiteSparse**に含まれるスパースLU分解ライブラリ。  
- 主にC言語で書かれており、OS固有のコードが少なく、数値アルゴリズム主体。  
- スレッドやBLAS/LAPACK依存をオフにするかEmscripten用にビルドすれば、比較的スムーズに移植できる可能性大。

### 3.2 SUNDIALS（ODE/DAEソルバ）
- CVODEやIDA、KINSOLなど多彩な数値ソルバ群。  
- シリアル版のみであればブラウザでも十分動作可能。  
- 並列化（MPIやOpenMP）を多用すると難易度が上がるが、オフにすれば移植しやすい。

**結論**：C/C++主体の数学ライブラリなので、**OS依存部分を外せばWebAssemblyに移植できる確率は高い**。

---

## 4. 実際にコンパイルする流れ（Emscriptenを例に）

以下の図は、C/C++ソースコードをEmscriptenでビルドして、ブラウザ上でWasmモジュールを呼び出すまでのフローを表しています。

```mermaid
flowchart TD
    A(C/C++ ソースコード) --> B(Emscripten/Clang)
    B -->|コンパイル| C(".wasm + .js 出力")
    C -->|ロード&実行| D(ブラウザ/JS)
    D -->|関数呼び出し| E(Wasmモジュール<br>高速計算)
    E -->|結果| D
```

1. **Emscriptenのインストール**  
   ```bash
   git clone https://github.com/emscripten-core/emsdk.git
   cd emsdk
   ./emsdk install latest
   ./emsdk activate latest
   source ./emsdk_env.sh
   ```
2. **ライブラリのソースを取得し、configure/cmake**  
   - `emconfigure ./configure` や `emcmake cmake ..` などEmscripten用のwrapperで環境設定  
3. **コンパイル・リンク**  
   - `emmake make`でビルド → `.wasm` + `.js`(ブリッジ) が生成  
   - または `emcc mylib.c -o mylib.js -s MODULARIZE=1 ...` 等の直接指定  
4. **JavaScript側でロード・呼び出し**  
   ```javascript
   const Module = await MyLib();   // EmscriptenのMODULARIZE生成
   const result = Module._my_function(123, 456);
   console.log(result);
   ```
   - Emscriptenの`cwrap`や`ccall`を使えばよりシンプルに呼び出せます

---

## 5. 結論とまとめ

- 調べた限り、**C/C++ライブラリをWebAssemblyにコンパイルできる確率**は、OS依存の少ない“数値計算系”や“アルゴリズム系”ならおおむね**7～8割以上**で成功するようです。  
- GUIや並列化、特殊なハードウェアアクセスが絡むほど移植は困難になります。  
- しかしながら、**電子回路シミュレータ内部で使われるKLUやSUNDIALS**などは、比較的OS依存が少ないため、**十分移植して動かせる可能性が高い**、と思いました。  
- 一度Wasm化できれば、ブラウザ上のUIやサーバーレス環境で強力なC/C++ライブラリを再利用できるため、**挑戦する価値は大いにある**と思います。

---

## FAQ

### Q1. EmscriptenでビルドしたWasmはネイティブコードと比べてどのくらい遅くなりますか？
A1. 一般的にはネイティブコードより多少のオーバーヘッドがありますが、JIT最適化やAOTを活用することで「おおむねネイティブの7〜9割程度」の性能が出ると言われています。起動時間やメモリ効率では有利な場合もあります。

### Q2. 逆アセンブルされてしまうリスクはどうすればいいですか？
A2. WebAssemblyはバイナリ形式ですが、読み出しや逆アセンブルを完全に防ぐことはできません。ソースコードを保護したい場合、**難読化**や**DRM**のような対策を検討する必要があります。

### Q3. ブラウザ以外でWasmを動かす場合でもC/C++ライブラリ移植はしやすいですか？
A3. サーバーサイドやサーバーレス環境（WASI対応ランタイムなど）でも、同様にEmscriptenやClangでコンパイルできます。ブラウザ特有のAPIは不要な分、さらにOS依存コードを排除しやすいかもしれません。

### Q4. MPIやOpenMPをどうしても使いたい場合、まったく無理なのでしょうか？
A4. WebAssemblyの**スレッドサポート**はあり、OpenMPの一部をサポートする試みがあります。ただしブラウザで有効にするにはSharedArrayBuffer等の仕組みが必要で、セキュリティ要件が厳しいです。MPIはさらに困難ですが、将来のWASI拡張に期待があるかもしれません。

### Q5. Spice本体すらWasm化することはできますか？
A5. SpiceはUNIX系APIに依存する部分も多いですが、理論上はEmscriptenで対応可能なところは多いです。GUIやマルチスレッド部分、外部プログラム呼び出し等を調整すれば、一部機能を削減しつつ移植する事例は考えられます。

### Q6. 大規模な数値計算（例えば100万以上の未知数を持つ方程式）をブラウザで実行するとパフォーマンスが不安です。
A6. 計算時間は実装やアルゴリズムに左右されますが、Wasmによるネイティブ級の性能向上があっても、ブラウザでの実行には**メモリ上限やタブのCPU時間制限**などがある場合があります。大規模計算はサーバーサイドWasmやエッジランタイムを検討するのも手です。

---

## まとめ

WebAssemblyは、**ブラウザからクラウド、エッジ、そしてIoTデバイス**までを繋ぐ汎用実行プラットフォームとして進化を続けています。特に、C/C++ライブラリのWasm化は以下のような利点があります。

- **SIMDやGC、例外処理**などで性能と柔軟性が向上（最新のWasm仕様ベース）  
- **WASI標準化**の進展により、ブラウザ外でも同様のアプローチが可能  
- 既存の大規模ライブラリ資産を**一から書き直す必要がなく**、エコシステムを活用できる  
- Spiceシミュレータの内部構造や数値ライブラリ（KLU、SUNDIALSなど）も移植しやすい部類

もちろん、GUI機能やOS固有API、並列化、ライセンスなどを考慮する必要がありますが、**総合的に見てC/C++ライブラリをWebAssemblyへ移植する成功率は高く、挑戦する価値は大いにある**と言えます。自分もこれから挑戦してみようと思います。

---

## 参考リンク

- [Emscripten公式サイト](https://emscripten.org/)  
- [Emscriptenチュートリアル: emccコマンドでのコンパイル方法](https://emscripten.org/docs/getting_started/Tutorial.html)  
- [SuiteSparse / KLU 公式リポジトリ](https://github.com/DrTimothyAldenDavis/SuiteSparse)  
- [SUNDIALS 公式サイト](https://computing.llnl.gov/projects/sundials)  
- [WebAssembly公式サイト](https://webassembly.org/)  

---

以上