Emacs で IPC や RPC (Emacs Advent Calendar jp: 2011)
Emacs Advent Calendar jp: 2011 : ATND 6日目の記事のはずでしたが、手違いでかぶってしまい、いろいろあって遅くなってしまいました。
皆様、乱してしまってすみません。
今回の記事では、EmacsでのIPC(Inter-Process Communication)やRPC(Remote Procedure Call)の方法について、自分の知っている範囲でまとめてみます。IPCは、プログラムの間で通信する仕組みです。RPCは、既に起動しているプログラムの一部(関数やサブルーチン)を別のプログラムから呼び出す仕組みです。一般的にIPCの枠にRPCが含まれます。
EmacsにはどんなIPC/RPCの実現方法があるのか、実際の応用例などを5分程度で簡単にまとめてみます。
Emacsの標準IPC手段
以下のようなものがあります。(Emacs 23 以上の場合)
- パイプ
- プロセスを起動してパイプで通信
- ソケット
- D-Bus
- Linux Desktop 環境向けの通信プロトコル
- D-Bus - Wikipedia
- ファイル読み書き
- 排他制御が必要
- emacsclient
- 起動中のEmacsとS式でのやりとり
ひと通り揃っていて、大体色々出来ますし、D-Bus以外はプラットフォーム中立の事を考えて作られています。
しかしながら、本格的なプログラミング環境としては細かい制御が出来ず、悔しい思いをすることが多いです。特に、共有ライブラリにリンクして、高機能・高パフォーマンスな通信手段(DB直接続とかmsgpackとか)を使うことが出来ません。
そのため、一般的には別の中継プログラムを作成して、パイプなどで通信してやりたい機能を実現するということが多いです。このあたりの歴史や状況については、 id:m2ym さんの文書 http://cx4a.org/pub/emacs-is-dead.ja.html が詳しいです。*1
IPC/RPC いろいろ
Emacsで行われている IPC/RPC の手段について簡単に紹介してみます。
コマンド起動
プログラムを起動し、結果を標準出力などからテキスト等で受け取る方式です。
同期的に呼べば簡単に使えますし、外部プログラムだけでデバッグもできるので楽です。
一方で、外部プログラムや設定がOSや環境に依存して動かないこともあります。が、他の方法よりもはるかに問題解決が楽です。
パイプ・ソケット
バックグラウンドで外部プログラムを起動し、パイプやソケットなどで通信する方法です。
非同期プログラミングが大変ですが、常に起動しているため応答の性能も良く、また外部プログラム側も状態を持つことができるので、出来ることが大幅に増えます。
- パイプで通信
- TCPソケットで通信
- SLIME / Swank
- IIIMECF(ATOK)
- ソケットで非同期通信
- キーイベント → 漢字変換、UI更新(非同期)
(2011/12/09 TCPソケットのところにパイプ通信が混じっていたのを修正)
D-Bus
D-Bus は Linux Desktop 上ではかなりデファクトに近いIPC環境になっています。
- D-Bus - Wikipedia (再掲)
1対1の通信だけではなく、必要なプロセスにイベント通知させたり、オブジェクトのシリアライズ、サービスのインスペクションなども出来るため、IPCとしてはかなり高機能です。
- 参考文献
skype.el でも使っていますが、これを積極的に利用したアプリケーションはほとんど無く、正直 D-Bus をEmacsでサポートする必要はなかった(もっと他にやることがあった?)のではないかとか思っています。
emacsclient
起動中のEmacsにファイルをオープンさせるような用途が圧倒的ですが、S式を送り込んで評価させたり出来るため、手軽なRPCとして利用できます。
HTTP / Webサービス
最近はインターネット上のサービスと通信する機会が多くなってきました。REST APIに直接アクセスしたり、XML-RPCなどで機能を手軽に呼び出すことが出来ます。
xml-rpc.el のように、標準のurlパッケージを使ってEmacs単独で通信することも出来ますが、るびきちさんも指摘する通り、細かいバグやSSL・プロキシ経由の通信で問題があるので、自前実装する場合は curl, wget を使う方が堅実だと思います。
Webサービスと通信する場合に問題になるのは認証です。一般的に以下の方法があります。
- OAuth
- Webアプリ向けの OAuth を実装する方法、コスト高い
- Twitterクライアントとかだと必須
- oauthライブラリ : EmacsWiki: O Auth Library
- twittering-mode は自前実装
- API key
- HTTPセッション Cookie
- 認証APIからクッキーを発行してもらって、以降の通信で使う
- 参考 : セッションキーとして出力されるCookieをwgetで保存する: hogepiyo
- あんまり見たこと無い。ページスクレイピング? リファラーとかCSRF対策は?
- BASIC認証
- ユーザーに認証情報を入れてもらう
- パスワードやユーザー情報を wget などに渡す必要がある
今後、Webサービスとの通信は増えてくると思いますので、この辺りの環境が整備されてくると便利になりそうです。
EPC に続く
これまでのIPC/RPCはプリミティブすぎる(パイプとかD-Busとか)か、特定の目的のための専用スタック(pymacsとかel4rとか)なので、別のプログラムを気軽に呼び出して使えるような、汎用のRPCスタックがありません。
例えば、EmacsはDBに直接接続することが出来ませんが、DBに接続して自由にSQLを発行してデータをやり取りできると、大変夢が広がります。さらに、これがPythonやRubyなどの専用スタックではなく、インタフェースは固定のまま、自分の好きな言語で拡張できると大変素敵です。
ということで、現在 EPC(Emacs Procedure Call)なるものをつくっています。YAPC Asia 2011の時にデモしたような、EmacsからPerlを自由に呼んでやりたい放題なことを実現できるようにする予定です。
Emacs - Perl 間はだいたい動くのですが、いきなり CPAN に上げる前に PrePAN でレビューをお願いしたいと思っています。
プロトコルの詳細などのドキュメントが固まり次第、お知らせする予定です。
おわり
本当にすみません。Advent Calendar は小粒なネタで毎日続けることが重要だと思いました。来年も参加するときは気をつけようと思います。
やっぱり1時間ぐらいかかりました。