您的位置:首页 > 其它

Erlang中通过Port与外部程序交互

2012-12-26 14:33 344 查看
Erlang与外部程序交互大概如下:



erlang:

-module(complex1).
-export([start/1, stop/0, init/1]).
-export([foo/1, bar/1]).

start(ExtPrg) ->
spawn(?MODULE, init, [ExtPrg]).
stop() ->
complex ! stop.

foo(X) ->
call_port({foo, X}).
bar(Y) ->
call_port({bar, Y}).

call_port(Msg) ->
complex ! {call, self(), Msg},
receive
{complex, Result} ->
Result
end.

init(ExtPrg) ->
register(complex, self()),
process_flag(trap_exit, true),
Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
loop(Port).

loop(Port) ->
receive
{call, Caller, Msg} ->
Port ! {self(), {command, encode(Msg)}},
receive
{Port, {data, Data}} ->
Caller ! {complex, decode(Data)}
end,
loop(Port);
stop ->
Port ! {self(), close},
receive
{Port, closed} ->
exit(normal)
end;
{'EXIT', Port, Reason} ->
exit(port_terminated)
end.

encode({foo, X}) -> [1, X];
encode({bar, Y}) -> [2, Y].

decode([Int]) -> Int.


[/code]
c程序:


/* erl_comm.c */

typedef unsigned char byte;

read_cmd(byte *buf)
{
int len;

if (read_exact(buf, 2) != 2)
return(-1);
len = (buf[0] << 8) | buf[1];
return read_exact(buf, len);
}

write_cmd(byte *buf, int len)
{
byte li;

li = (len >> 8) & 0xff;
write_exact(&li, 1);

li = len & 0xff;
write_exact(&li, 1);

return write_exact(buf, len);
}

read_exact(byte *buf, int len)
{
int i, got=0;

do {
if ((i = read(0, buf+got, len-got)) <= 0)
return(i);
got += i;
} while (got<len);

return(len);
}


/* port.c */

typedef unsigned char byte;

int main() {
int fn, arg, res;
byte buf[100];

while (read_cmd(buf) > 0) {
fn = buf[0];
arg = buf[1];

if (fn == 1) {
res = foo(arg);
} else if (fn == 2) {
res = bar(arg);
}

buf[0] = res;
write_cmd(buf, 1);
}
}


编译执行:

unix> gcc -o extprg complex.c erl_comm.c port.c

unix> erl
Erlang (BEAM) emulator version 4.9.1.2

Eshell V4.9.1.2 (abort with ^G)
1> c(complex1).
{ok,complex1}
2> complex1:start("extprg").
<0.34.0>
3> complex1:foo(3).
4
4> complex1:bar(5).
10
5> complex1:stop().
stop

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: