! ThriftでOCamlクライアントを書く
Thriftはいろんな言語で利用可能 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml.
!! Hello World(サーバーはC++、クライアントはOCaml) IDL(インターフェース定義言語)
service Hello { string hello(1: string name) }
Thriftでサーバー(C++)、クライアント(OCaml)を生成
$ thrift --gen cpp --gen ocaml hello.thrift
!! サーバーロジックを書く
Hello_server.skeleton.cpp
class HelloHandler : virtual public HelloIf { public: HelloHandler() { // Your initialization goes here } void hello(std::string& _return, const std::string& name) { // Your implementation goes here _return.append("Hello ").append(name); } };
!! サーバーをコンパイル
$ g++ -g Hello_server.skeleton.cpp Hello.cpp -o Hello_server -lthrift -I/usr/local/include/thrift
!! クライアントを書く
Hello_client.mlを新規作成して内容はこうする。
open Thrift;; open Hello_types;; let s = new TSocket.t "localhost" 9090;; let p = new TBinaryProtocol.t s;; let c = new Hello.client p p;; s#opn; print_string (c#hello "Gemma"); print_char '\n'; s#close;
!! クライアントをコンパイルする
Makefileを使うべし。
SOURCES = ./gen-ocaml/hello_types.ml ./gen-ocaml/hello_consts.ml ./gen-ocaml/Hello.ml Hello_client.ml RESULT = test_client INCDIRS = "./Desktop/thrift/lib/ocaml/src/" "./gen-ocaml/" LIBS = unix thrift all: nc OCAMLMAKEFILE = ./Desktop/thrift/lib/ocaml/OCamlMakefile include $(OCAMLMAKEFILE)
このMakefileの実行結果
make[1]: ディレクトリ `/home/teruaki' に入ります ocamldep -I ./gen-ocaml/ Hello_client.ml > ._d/Hello_client.d ocamldep -I ./gen-ocaml/ gen-ocaml/Hello.ml > ._d/./gen-ocaml/Hello.d ocamldep -I ./gen-ocaml/ gen-ocaml/hello_consts.ml > ._d/./gen-ocaml/hello_consts.d ocamldep -I ./gen-ocaml/ gen-ocaml/hello_types.ml > ._d/./gen-ocaml/hello_types.d make[1]: ディレクトリ `/home/teruaki' から出ます make[1]: ディレクトリ `/home/teruaki' に入ります ocamlc -c -I ./gen-ocaml/ -I ./Desktop/thrift/lib/ocaml/src/ -I ./gen-ocaml/ gen-ocaml/hello_types.mli ocamlopt -c -I ./gen-ocaml/ -I ./Desktop/thrift/lib/ocaml/src/ -I ./gen-ocaml/ gen-ocaml/hello_types.ml ocamlopt -c -I ./gen-ocaml/ -I ./Desktop/thrift/lib/ocaml/src/ -I ./gen-ocaml/ gen-ocaml/hello_consts.ml ocamlc -c -I ./gen-ocaml/ -I ./Desktop/thrift/lib/ocaml/src/ -I ./gen-ocaml/ gen-ocaml/Hello.mli ocamlopt -c -I ./gen-ocaml/ -I ./Desktop/thrift/lib/ocaml/src/ -I ./gen-ocaml/ gen-ocaml/Hello.ml ocamlopt -c -I ./gen-ocaml/ -I ./Desktop/thrift/lib/ocaml/src/ -I ./gen-ocaml/ Hello_client.ml ocamlopt \ \ -I ./gen-ocaml/ -I "./Desktop/thrift/lib/ocaml/src/" -I "./gen-ocaml/" -ccopt -L./gen-ocaml/ unix.cmxa thrift.cmxa -o tc \ ./gen-ocaml/hello_types.cmx ./gen-ocaml/hello_consts.cmx ./gen-ocaml/Hello.cmx Hello_client.cmx make[1]: ディレクトリ `/home/teruaki' から出ます
!!実行
!!!サーバーを立ち上げる
$ gen-cpp/Hello_server Thrift: Wed Sep 24 17:37:19 2008 TServerSocket::listen() IPV6_V6ONLY Protocol not available
!!!クライアントを立ち上げる
$ ./test_client Hello Gemma
!!クライアントのソースを比べる
上で使ったOCaml製クライアント
open Thrift;; open Hello_types;; let s = new TSocket.t "localhost" 9090;; let p = new TBinaryProtocol.t s;; let c = new Hello.client p p;; s#opn; print_string (c#hello "Gemma"); print_char '\n'; s#close;
Perl製クライアント
use lib './gen-perl';
## Thrift インストール時にインストールされているライブラリ群 use Thrift; use Thrift::BinaryProtocol; use Thrift::Socket; ## IDL から gen-perl/ 以下に生成されたライブラリ use Hello; my $transport = Thrift::Socket->new('localhost', 9090); my $client = HelloClient->new( Thrift::BinaryProtocol->new($transport) ); $transport->open(); printf "%s\n", $client->hello("Gemma"); $transport->close();
Ruby製クライアントは試してないけど、きっとこんな感じ。
require 'thrift/transport/tsocket' require 'thrift/protocol/tbinaryprotocol' require 'Hello' transport = TSocket.new('localhost', 9090) client = Hello::Client.new( TBinaryProtocol.new(transport)) transport.open puts client.hello("Gemma") transport.close
言語がちがってもそっくりだ!
サーバーもC++に限らず、いろんな言語で書ける。