Hatena::ブログ(Diary)

技術日記@kiwanami

2011-12-06

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以外はプラットフォーム中立の事を考えて作られています。

しかしながら、本格的なプログラミング環境としては細かい制御が出来ず、悔しい思いをすることが多いです。特に、共有ライブラリにリンクして、高機能・高パフォーマンスな通信手段(DB直接続とかmsgpackとか)を使うことが出来ません。

そのため、一般的には別の中継プログラムを作成して、パイプなどで通信してやりたい機能を実現するということが多いです。このあたりの歴史や状況については、 id:m2ym さんの文書 Page not found · GitHub Pages が詳しいです。*1

IPC/RPC いろいろ

Emacsで行われている IPC/RPC の手段について簡単に紹介してみます。

コマンド起動

プログラムを起動し、結果を標準出力などからテキスト等で受け取る方式です。

同期的に呼べば簡単に使えますし、外部プログラムだけでデバッグもできるので楽です。

一方で、外部プログラムや設定がOSや環境に依存して動かないこともあります。が、他の方法よりもはるかに問題解決が楽です。

パイプ・ソケット

バックグラウンドで外部プログラムを起動し、パイプやソケットなどで通信する方法です。

非同期プログラミングが大変ですが、常に起動しているため応答の性能も良く、また外部プログラム側も状態を持つことができるので、出来ることが大幅に増えます。

(2011/12/09 TCPソケットのところにパイプ通信が混じっていたのを修正)

D-Bus

D-BusLinux Desktop 上ではかなりデファクトに近いIPC環境になっています。

1対1の通信だけではなく、必要なプロセスにイベント通知させたり、オブジェクトシリアライズ、サービスのインスペクションなども出来るため、IPCとしてはかなり高機能です。

skype.el でも使っていますが、これを積極的に利用したアプリケーションはほとんど無く、正直 D-BusEmacsでサポートする必要はなかった(もっと他にやることがあった?)のではないかとか思っています。

emacsclient

起動中のEmacsにファイルをオープンさせるような用途が圧倒的ですが、S式を送り込んで評価させたり出来るため、手軽なRPCとして利用できます。

HTTP / Webサービス

最近はインターネット上のサービスと通信する機会が多くなってきました。REST APIに直接アクセスしたり、XML-RPCなどで機能を手軽に呼び出すことが出来ます。

xml-rpc.el のように、標準のurlパッケージを使ってEmacs単独で通信することも出来ますが、るびきちさんも指摘する通り、細かいバグSSLプロキシ経由の通信で問題があるので、自前実装する場合は curl, wget を使う方が堅実だと思います。

Webサービスと通信する場合に問題になるのは認証です。一般的に以下の方法があります。

今後、Webサービスとの通信は増えてくると思いますので、この辺りの環境が整備されてくると便利になりそうです。

EPC に続く

これまでのIPC/RPCはプリミティブすぎる(パイプとかD-Busとか)か、特定の目的のための専用スタック(pymacsとかel4rとか)なので、別のプログラムを気軽に呼び出して使えるような、汎用のRPCスタックがありません。

例えば、EmacsDBに直接接続することが出来ませんが、DBに接続して自由にSQLを発行してデータをやり取りできると、大変夢が広がります。さらに、これがPythonRubyなどの専用スタックではなく、インタフェースは固定のまま、自分の好きな言語で拡張できると大変素敵です。

ということで、現在 EPC(Emacs Procedure Call)なるものをつくっています。YAPC Asia 2011の時にデモしたような、EmacsからPerlを自由に呼んでやりたい放題なことを実現できるようにする予定です。

Emacs - Perl 間はだいたい動くのですが、いきなり CPAN に上げる前に PrePAN でレビューをお願いしたいと思っています。

プロトコルの詳細などのドキュメントが固まり次第、お知らせする予定です。

おわり

本当にすみません。Advent Calendar は小粒なネタで毎日続けることが重要だと思いました。来年も参加するときは気をつけようと思います。

やっぱり1時間ぐらいかかりました。

*1:ちなみに、自分も Emacs 自体が単純に肥大化していくことにはちょっと違和感があります。単純に機能が増えるよりも、パッケージや汎用的な通信手段で簡単に拡張できることに集中したほうがいいと思っています。

tkf41tkf41 2012/11/14 21:54 > これまでのIPC/RPCはプリミティブすぎる(パイプとかD-Busとか)

これから EPC の記事を書く予定があれば、 D-Bus が EPC に比べてプリミティブだという理由について説明してもらえませんか? Python-EPC 作った後に、良く考えたら D-Bus で良かったんじゃないかと思ってしまいました。 Windows でも動かすなら D-Bus 使えないとは思いますが。

kiwanamikiwanami 2012/11/15 10:49 すぐに書けないかもしれないので、ここで簡単にご説明します。

欲しかったものはEmacsが動けば大体どこでも動いて、数行のコードで1対1のRPCを気軽に構築できるものでした。そういう意味で、パイプはRPC層から作らないといけない、DBusは汎用的すぎてRPCを立てる前に勉強することが多いということからプリミティブだと表現しました。ちょっと急いで書いた記事なので、説明不足で申し訳ないです。

EPCについてですが、skype.elを作った時に、MacやWindowsで動かしたいという声がかなり多かったので、OSに依存しないようにしたいという動機もありました。もちろんMacではdbusを別途入れるとdbusは動くのですが、dbusをMacで動かすことはあんまりメジャーではないような気がしていて、そうするとEmacsのRPCのためにdbusを入れてもらうのも厳しいかなと感じております。

dbusはすごく良く出来ていて、EmacsでRPCやりたいと思うような人はdbusぐらい出来ると思いますし、CORBAとかCOMとか経験してきた身としては、これがWindowsでも気軽に動けばいいのになあと思う所であります。ですので、dbusが使える状況であれば、RPC層としてはdbusはとても優れた選択肢だと思います。

ということで、dbusよりEPCを選ぶとすると、Windows上での動作なのかなと思います。

tkf41tkf41 2012/11/25 01:00 ありがとうございます。今まで返信に気づきませんでした。やはり、メインの問題はプラットフォーム依存性だったんですね。あと確かに dbus は面倒ですよね。マニュアルも充実していないように思えます。 dbus は動的言語だと型指定が面倒なので、動的言語同士だと EPC の方が自然に書けると思いました。これはdbusのAPIを適当にラップすれば済む問題ではありますが。