🐈

Bun の C Compile を試してみた

2024/10/14に公開
1

はじめに

先日、Bun が C Compiler を搭載し、JS と C の相互変換が簡単にできるようになったということで、試してみました。

https://bun.sh/blog/compile-and-run-c-in-js#bun-ffi-is-low-overhead

migemo

題材を探していたところ、エンジニアの楽園のヌコ様から、cmigemoを試してみてはどうかという提案をいただきました。

0.png

てなわけでやっていきます!

bun-cmigemo

以下のレポジトリに、cmigemo を使ったサンプルプログラムを置いています。
https://github.com/ryoppippi/bun-cmigemo

また、npmにも公開しています。

https://www.npmjs.com/package/bun-cmigemo

bunを使えば事前コンパイルが必要ないので、なんと、Cのファイルをそのままnpmに上げています。

1.png

使い方

辞書ファイルが手元にあれば、

bun i bun-cmigemo
bun pm trust bun-cmigemo # cmigemoのコードをpostinstallで落としてくるので、許可が必要

でインストール後、

import { Migemo } from 'bun-cmigemo';

const dictPath = '/absolute/path/to/dict';
{
	using migemo = new Migemo(dictPath);

	migemo.query(query, s => console.log(s));
}

で、cmigemo を使うことができます。

また、Hono を使った簡単なサンプルも置いています。

https://github.com/ryoppippi/bun-cmigemo/blob/d7e28a23e874c2f1a1a74108ed9227dc73308ebe/app/index.tsx

2.gif

簡単なコード解説

本当に簡単にCのコードが呼び出せたので、あまり解説することはありませんが、一応。

まず、cmigemo の関数をラップした関数をCで書きます。
https://github.com/ryoppippi/bun-cmigemo/blob/d7e28a23e874c2f1a1a74108ed9227dc73308ebe/lib/main.c

今回は3つの関数を定義しました。

  • migemoOpen: 辞書ファイルを開いて migemo インスタンスを作成する
  • migemoQuery: 引数として、migemo インスタンス、クエリ、callback 関数を受け取り、クエリにマッチする文字列を callback 関数に渡す。callback 関数実行後、結果を free する。
  • migemoClose: migemo インスタンスを free する。

次に、上で定義した関数を呼び出すために、bun cc 関数を使って定義を書いていきます。
https://github.com/ryoppippi/bun-cmigemo/blob/d7e28a23e874c2f1a1a74108ed9227dc73308ebe/lib/index.ts#L12-L37

やはり面白いのは JS の callback 関数を C に渡せるところですね。
文字列を直接戻り値として渡してもよかったのですが、メモリの確保や解放が面倒だったので、今回は callback 関数を使いました。

これで終わりでも良いのですが、ユーザーがいちいち migemoOpenmigemoClose を呼び出すのは面倒なので、これらをいい感じにラップして、Migemo クラスを作りました。

https://github.com/ryoppippi/bun-cmigemo/blob/d7e28a23e874c2f1a1a74108ed9227dc73308ebe/lib/index.ts#L54-L90

ポイントは、

  • Migemo クラスを using migemo = new Migemo('./migemo-dict'); でインスタンス化することで、scope から外れると自動的に migemoClose が呼ばれる
  • migemo.query で クエリと callback 関数を渡すことで、migemoQuery が呼ばれる (結果は callback 関数に渡され、callback 関数が終了した後にメモリが解放される)

おわりに

今回は、cmigemo を使ってみましたが、他にもいろいろなライブラリを使ってみたいと思います。
楽しいですね!

Discussion

ryoppippiryoppippi

補足です!
cmigemoのライブラリの作法として、「結果を文字列として返し、その文字列のはいっているメモリは解放しないといけない」という前提があります。なので、本文でたびたび「メモリの解放」という文言が出てきますが、それはcmigemoにおけるメモリ解放を指しています。

また加えて、実際の実装ではJavaScriptのcallback関数に対するメモリの解放も行っているのですが、本文中では触れていません。コードとドキュメントを参照してください。