|
|
把<Programming Erlang>书上第12章那个erlang-c的例子改编了下,把C程序改写成了python程序。在ubuntu8.04 + erlang5.6.5 + python2.5.2上调试通过。
erlang side: example2.erl
-module(example2).-export([start/0, stop/0]).-export([twice/1, sum/2]).start() -> spawn(fun() -> register(example1, self()), process_flag(trap_exit, true), Port = open_port({spawn, "python -u ./example2.py"}, [{packet, 2}]), loop(Port) end).stop() -> example1 ! stop.twice(X) -> call_port({twice, X}).sum(X,Y) -> call_port({sum, X, Y}).call_port(Msg) -> example1 ! {call, self(), Msg}, receive{example1, Result} -> Result end.loop(Port) -> receive{call, Caller, Msg} -> Port ! {self(), {command, encode(Msg)}}, receive{Port, {data, Data}} -> Caller ! {example1, decode(Data)} end, loop(Port);stop -> Port ! {self(), close}, receive{Port, closed} -> exit(normal) end;{'EXIT', Port, Reason} -> exit({port_terminated,Reason}) end.encode({twice, X}) -> [1, X]; encode({sum, X, Y}) -> [2, X, Y]. decode([Int]) -> Int.
需要注意的是调用python程序,要使用参数-u。强制标准输入/输出不得有缓存,要立时反应。
python官方文档对-u的解释: Force stdin, stdout and stderr to be totally unbuffered.
python side: example2.py
import sys, osimport structdef recv(): buf = sys.stdin.read(2) if len(buf) == 2: (sz, ) = struct.unpack("!h", buf) payload = sys.stdin.read(sz) return payload else: return Nonedef send(payload): sz = len(payload) header= struct.pack("!h", sz) return sys.stdout.write( header + payload )def twice(arg1): return 2*arg1def sum(arg1,arg2): return arg1+arg2def main_loop(): buf = recv() while buf: xa = struct.unpack("!%dB" % len(buf), buf) if xa[0] == 1: calc_res = twice(xa[1]) elif xa[0] == 2: calc_res = sum(xa[1], xa[2]) result = struct.pack('!B', calc_res) send(result) buf = recv() return Noneif __name__ == '__main__': main_loop() |
|