[[ocaml-nagoya]]
#contents
* ThriftでOCamlクライアントを書く [#hb5016a6]
Thriftはいろんな言語で利用可能
C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml.
- OCaml用パッチが必要かも? https://issues.apache.org/jira/browse/THRIFT-125
** Hello World(サーバーはC++、クライアントはOCaml) [#qec0d9e3]
IDL(インターフェース定義言語)
service Hello
{
string hello(1: string name)
}
Thriftでサーバー(C++)、クライアント(OCaml)を生成
$ thrift --gen cpp --gen ocaml hello.thrift
** サーバーロジックを書く [#ce0becbb]
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);
}
};
** サーバーをコンパイル [#p1f2eb95]
$ g++ -g Hello_server.skeleton.cpp Hello.cpp -o Hello_server -lthrift -I/usr/local/include/thrift
** クライアントを書く [#y6d79ab5]
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;
** クライアントをコンパイルする [#d58f68ca]
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' から出ます
**実行 [#b1124b3e]
***サーバーを立ち上げる [#t1ecd1a6]
$ gen-cpp/Hello_server
Thrift: Wed Sep 24 17:37:19 2008 TServerSocket::listen() IPV6_V6ONLY Protocol not available
***クライアントを立ち上げる [#oe39713e]
$ ./test_client
Hello Gemma
**クライアントのソースを比べる [#q42d8cb1]
上で使った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++に限らず、いろんな言語で書ける。