Inlineで遊ぼう - Shibuya Perl Mongers

Inlineで遊ぼう
Tomohiro IKEBE <[email protected]>
EDGE Co., ltd.
Shibuya.pm Techinical Talks
目次
Inline とは
なぜInlineなのか
Inline::C
Inline::Java
Inline::Ruby
ILSM を作る
まとめ
Inline とは
DESCRIPTION
The Inline module allows you to put source code from other programming
languages directly "inline" in a Perl script or module. The code is
automatically compiled as needed, and then loaded for immediate access from
Perl.
Perl プログラムの中に “直接” 他の言語を記述するためのモジュール
コンパイルが必要な場合は自動的にコンパイルされ、他の言語で書かれたサ
ブルーチンやクラスをPerlから使用する事が出来る。
C,C++ の他に ILSM (Inline Language Support Module) と呼ばれる機構により、
様々な言語を使用する事が出来る。
ILSM
Inline::ASM
Inline::Awk
Inline::BC
Inline::Basic
Inline::Befunge
Inline::C
Inline::CPP
Inline::Guile
Inline::Java
Inline::Octave
Inline::Python
Inline::Ruby
Inline::Slang
Inline::SMITH
Inline::TT
Inline::Tcl
Inline::WebChat
Acme::Inline::PERL
Inline 以前
XS
Perl 標準の拡張方法
マクロを使って記述
モジュールを作成する事が前提
SWIG (http://www.swig.org/)
Perl 以外の言語も対応
定義ファイルからソースコードを生成
なぜInlineなのか
より高速な言語で一部を記述する。
既存の資産を利用する。
XSやSWIGはめんどくさい。
たまには他の言語もいいかな。。
Inline::C
• 初回起動時はコンパイル処理が入るので遅い
% time ./ghttp.pl
3.440u 1.140s 0:06.23 73.5%
% time ./ghttp.pl
0.190u 0.060s 0:00.33 75.7%
0+0k 62+12io 0pf+0w
0+0k 0+1io 0pf+0w
• カレントディレクトリに _Inline ディレクトリが生成され、その内部で
コンパイル処理が行われる。
• Perl <=> C で取り扱える型。
• int
• long
• double
• char*
• void
• SV*
Inline::C
• ヒアドキュメントで記述
use Inline C =><<‘C_SOURCE’;
void say_hello (){ printf(“Hello World!\n”); }
C_SOURCE
say_hello();
• __DATA__ を使用
use Inline C => ‘DATA’;
say_hello();
__DATA__
__C__
void say_hello (){ printf(“Hello World!\n”); }
外部ライブラリの使用
外部ライブラリを使用する。
use strict;
use Inline C => Config =>
LIBS => '-L/sw/lib -lghttp',
INC => '-I/sw/include';
print get('http://www.google.co.jp/');
__END__
__C__
#include <ghttp.h>
SV *get(SV* uri) {
SV* buffer;
malloc(sizeof(char) * 1024 * 10);
ghttp_request* request;
buffer = NEWSV(0,0);
request = ghttp_request_new();
ghttp_set_uri(request, SvPV(uri, PL_na));
ghttp_set_header(request, http_hdr_Connection, "close");
ghttp_prepare(request);
ghttp_process(request);
sv_catpv(buffer, ghttp_get_body(request));
ghttp_request_destroy(request);
return buffer;
}
Inline::Java
Java のクラスをPerlのクラスに
外部 Java クラスの使用
サーバとして動作する RPC
JNI によるnative インターフェース
Velocity を実行する。
Jakarta Project の Velocity を Perl による Web アプリケーションの
テンプレートエンジンとして使用する。
便利かどうかは微妙なところ。。
use strict;
use Inline (
Java => ‘DATA’, # DATA セクションに記述する
CLASSPATH => ‘/path/to/velocity-1.3.jar’, # CLASSPATH を追加
DIRECTORY => ‘/tmp’, # httpd に書きこめるディレクトリ
SHARED_JVM => 1, # JVM を共有する
STUDY => [‘java.util.HashMap’], # HashMap を使用する
);
use CGI;
Inline::Java::release_JVM();
Velocity を実行する。
my $q = CGI->new;
print $q->header;
my $v = VelocityWrapper->new;
my $map = java::util::HashMap->new(); # STUDY!
$map->put($_, $q->param($_)) for $q->param; # パラメータ
$v->set("request", $map);
print $v->process("test.vm");
__DATA__
__Java__
#….
Velocity を実行する。
import java.io.StringWriter;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.VelocityContext;
import java.util.Properties;
class VelocityWrapper {
VelocityContext context = null;
public VelocityWrapper(){
try {
Velocity.init(new Properties());
}
catch(Exception ex){
ex.printStackTrace();
}
context = new VelocityContext();
}
public void set(String key, Object obj){
context.put(key, obj);
}
public String process(String filename) throws Exception{
StringWriter w = new StringWriter();
Velocity.mergeTemplate(filename, context, w );
return w.toString();
}
}
Inline::Ruby
Ruby のクラスをPerlから使用する。
組み込み型の相互変換。
rb_eval 関数
HTML::ERuby
http://search.cpan.org/dist/HTML-ERuby/
Eruby を Perl で実装。
Eruby の文法を Perl でパースし、Rubyのソースコードを生成 rb_eval
しているだけ
Perl の Web アプリケーションでテンプレート的に使用。
my %vars = (‘@var’ => ‘foo’, # Ruby instance variable
‘ARRAY_REF’ => [qw(a b c)], # Ruby constant
‘hash_ref’ => {foo => ‘bar’, ‘bar’ => ‘baz’});
my $compiler = HTML::ERuby->new;
print $compiler->compile(filename => ‘./foo.rhtml’,
vars => ¥%vars);
HTML::ERuby
Ruby -> Perl のデータ受け渡しはあるが逆はサポートされてない。
Perl の HASH_REF, ARRAY_REF は見た目的に Ruby の配列、ハッシュ
と似てる。。
そこで、Data::Dumper で Dump して Ruby で eval する事により配列、ハッ
シュを引渡す。
In Perl.
my %hash = (a => ‘foo’, b => ‘bar’);
my $str = Dumper \%hash;
$str =~ s/\$VAR1=//;
In Ruby
hash = eval $str
まとめ
まっとうに使うなら C, C++
Java は進化してきている。
スクリプト系は型のサポートが微妙
誰か Inline::PHP 作って。