libuv の Perl バインディング
気分転換プロジェクトとして、libuvのPerlバインディングを書いている。
現状、timerとtcp周りを一通り実装したところ。
実装は愚直にlibuvの関数とperlの関数を1:1に(uv_tcp_init(...)
をUV::tcp_init(...)
というような形で)マッピングしている。 この実装はlow level APIと位置づけ、その上に使いやすい高レベルなインタフェースをPerl上で用意したいつもり。
このlow level APIをつかったTCP echo serverはこんな感じになる:
use strict;
use warnings;
use UV;
my $server = UV::tcp_init();
UV::tcp_bind($server, '0.0.0.0', 3000)
&& die 'bind error: ', UV::strerror(UV::last_error());
UV::listen($server, 10, sub {
my $client = UV::tcp_init();
UV::accept($server, $client) && die 'accept failed: ', UV::strerror(UV::last_error());
UV::read_start($client, sub {
my ($nread, $buf) = @_;
if ($nread < 0) {
my $err = UV::last_error();
if ($err != UV::EOF) {
warn 'client read error: ', UV::strerror($err);
}
UV::close($client);
}
elsif ($nread == 0) {
# nothing to read
}
else {
UV::write($client, $buf, sub {
my ($status) = @_;
if ($status) {
warn 'client write error: ', UV::strerror(UV::last_error());
UV::close($client);
}
});
}
});
}) && die 'listen error: ', UV::strerror(UV::last_error());
UV::run();
見てわかるようにperlモジュールとしての使いかってはわるいが、libuvを使い慣れた人なら迷いなく使うことが出来るようになっている。 これは僕にとっては発見だった。
また、このサンプルをみてもわかるようにlisten
とかaccept
とかまでラップしている関係上、libuvをAnyEventのバックエンドとしてつかうのは現状は無理そう。
libuv自体はWindowsでも動くはずだが、メインマシンをAirにして以来Windows環境を仮想環境でも持ち歩いていないため確認できていない。 Windows対応してくれる人募集!
開発を始めるためのステップ:
$ cpanm Module::Install
$ cpanm Module::Install::XSUtil
$ git clone git://github.com/typester/p5-UV.git
$ cd p5-UV
$ git submodule update --init
$ perl Makefile.PL
$ make
$ make test