前書き
JavaとPythonで作ったシステムを統合したい,Javaで実装したシステムをPythonスクリプトで気軽に操作できるようにしたい,という必要に迫られて実験.
最初は自分で適当にプロトコル決めるかなーとか思っていたけど,MessagePack-RPCがとっても便利そうだったのでのっかることに.
やってみたこと
要は,Java側のメソッドをPythonから呼ぶ,Python側のメソッドをJavaから呼ぶというのがしたいこと.もちろん,引数や返り値も扱えないといけない.
というわけで,今回は,
- 文字列を渡してとHelloつきの文字を返してもらう(hello)
- 2つの引数を渡して足した値を返してもらう(add)
- 数の配列を渡して合計値を返してもらう(sum)
- 数の配列を渡して,matplotlibで作った折れ線グラフイメージを返してもらう(make_graph)
というのをやってみます.サーバー側がPython,クライアント側がJavaです.
コード
Python側のコード
server.py
import msgpackrpc
import matplotlib.pyplot as plt
from PIL import Image
class TestServer(object):
def hello(self, mesg):
print(mesg)
return ("Hello, " + mesg.decode()).encode()
def add(self, a, b):
return a + b
def sum(self, d):
return sum(d)
def make_graph(self, d):
plt.plot(d)
plt.savefig('hoge.png')
f = open('hoge.png', 'rb')
d = f.read()
f.close()
return d
server = msgpackrpc.Server(TestServer())
server.listen(msgpackrpc.Address("localhost", 1985))
server.start()
Java側のコード
TestClient.java
import org.msgpack.rpc.Client;
import org.msgpack.rpc.loop.EventLoop;
import org.msgpack.type.Value;
import java.io.*;
import java.util.*;
import java.awt.image.*;
import javax.swing.*;
import javax.imageio.*;
public class TestClient {
public static void main(String[] args) throws Exception {
EventLoop loop = EventLoop.defaultEventLoop();
Client client = new Client("localhost", 1985, loop);
int v;
System.out.println(" --- hello ---");
Value result = client.callApply("hello", new Object[]{"miyo"});
System.out.println("Result type:" + result.getType());
String s = new String(result.asRawValue().getByteArray());
System.out.println(s); // Hello, miyo
System.out.println();
System.out.println(" --- add --- ");
result = client.callApply("add", new Object[]{100, 10}); // 110
System.out.println("Result type:" + result.getType());
v = result.asIntegerValue().getInt();
System.out.println("result = " + v + " :" + (v == 110));
System.out.println();
System.out.println(" --- sum --- ");
result = client.callApply("sum", new Object[]{new int[]{1, 2, 3, 4, 5}}); // 15
System.out.println("Result type:" + result.getType());
v = result.asIntegerValue().getInt();
System.out.println("result = " + v + " :" + (v == 15));
System.out.println();
System.out.println(" --- make graph ---");
result = client.callApply("make_graph",
new Object[]{new int[]{1,2,4,8,10,3,6,8,9,-1}});
System.out.println("Result type: " + result.getType());
byte[] raw = result.asRawValue().getByteArray();
BufferedImage img = ImageIO.read(new ByteArrayInputStream(raw));
System.out.println(img);
Icon icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null,
"",
"image",
JOptionPane.PLAIN_MESSAGE,
icon);
client.close();
loop.shutdown();
}
}
実行結果
で
いやー,便利だわ!!
参考
いろいろ参考にしすぎてメモしそこねた...
- https://github.com/msgpack/msgpack-java/wiki/QuickStart
- http://grepcode.com/file/repo1.maven.org/maven2/org.msgpack/msgpack/0.6.4/org/msgpack/type/Value.java#Value
- https://github.com/msgpack-rpc/msgpack-rpc
- https://github.com/msgpack-rpc/msgpack-rpc-java
- https://github.com/msgpack-rpc/msgpack-rpc-python
- http://www.ne.jp/asahi/hishidama/home/tech/java/image.html
- http://d.hatena.ne.jp/heavenshell/20110802/1312277616