RubyInlineでSunRPCをたたいてみる
RubyコードにCコードを直接埋め込む RubyInline。
これを使って SunRPC サーバーを叩いてみました。
使用する RPCサーバーはこれ。
- sample.x
struct samplearg { int a; int b; }; struct sample { int sum; int diff; }; program SAMPLEPROG { version SAMPLEVERSION { sample SAMPLE(samplearg) = 1; } = 1; } = 0x20001001;
- sample_server.c
#include <rpc/rpc.h> #include "sample.h" bool_t sample_1_svc(samplearg* arg, sample* result, struct svc_req* req) { result->sum = arg->a + arg->b; result->diff = arg->a - arg->b; return TRUE; } int sampleprog_1_freeresult(SVCXPRT* svc, xdrproc_t proc, caddr_t caddr) { return 1; }
クライアント側の Rubyコード
- rubyrpc.rb
#!/usr/bin/env ruby require 'rubygems' require 'inline' class SunRPC_sample inline(:C) {|builder| builder.include "<rpc/rpc.h>" builder.include "\"sample.h\"" builder.add_compile_flags "sample_clnt.c sample_xdr.c -I #{File.dirname(__FILE__)}" builder.add_static "gClient", 0, "CLIENT*" builder.c <<-__C__ int start(void) { if(gClient) return 0; gClient = clnt_create("localhost", SAMPLEPROG, SAMPLEVERSION, "tcp"); if(gClient==NULL) { clnt_pcreateerror("localhost"); return -1; } return 0; } __C__ builder.c <<-__C__ int sum(int a, int b) { if(!gClient) return 0; sample result; samplearg arg = {a, b}; sample_1(&arg, &result, gClient); return result.sum; } __C__ builder.c <<-__C__ int diff(int a, int b) { if(!gClient) return 0; sample result; samplearg arg = {a, b}; sample_1(&arg, &result, gClient); return result.diff; } __C__ } end r = SunRPC_sample.new r.start puts r.sum(1, 2) puts r.diff(1, 2)
サーバーを起動しておいて、
$ rpcgen -M sample.x $ gcc -o sample sample_svc.c sample_server.c sample_xdr.c $ ./sample
Rubyクライアントを実行。
$ ./rubyrpc.rb 3 -1
成功\(゚∀゚)/