免責事項:質問の作者のErlangの平均知識を持っているとC.の基本的な(しかし増加)知識読む/ C
私が使用していますread()
は、私のport.c
プログラムがInteroperability Tutorial User Guideで提供されているErlangポートの例から取得したバイトを読み込む機能を持っています(「Erlang Programming」の第12章にも記載されています)。
しかし、C面からは間違った値(999の代わりに231など)が出てくるので、質問はErlangに関連していないと思う傾向があります。
問題は、このプロトコルは255以上のパラメータでは機能しないことです(それ以外の場合はうまくいきます)。私はそれがbyte
タイプとread_exact()
実装で何かを持っていると思いますが、それを修正する方法やそれにfloat
の値を渡すことはできません。
このコードを理解するためにK & R本の半分を読みましたが、まだ固まっています。ここ
コードである:
実際C関数:
/* complex.c */
int foo(int x) {
return x+1;
}
int bar(int y) {
return y*2;
}
Cポート:
/* 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);
}
}
バッファ管理:
/* 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);
}
write_exact(byte *buf, int len)
{
int i, wrote = 0;
do {
if ((i = write(1, buf+wrote, len-wrote)) <= 0)
return (i);
wrote += i;
} while (wrote<len);
return (len);
}
アーランポート:
-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.
私は
typedef int byte;
に
typedef unsigned char byte;
を変更するには、愚かな試みを行っているが、それはうまくいきませんでした。
実際には、二つの問題があります。
- 我々は255よりも大きいパラメータ、(アーランポートから例えば
foo(256)
)とポートを呼び出した場合、実行は(読み取り時に終了します)read_cmd内部が()をi = 0とする。 - 255より小さいパラメータでポートを呼び出すが、関数の結果が255より大きい場合(たとえば、
int foo(int x) { return x+1000; }
とすると、プログラムは終了しないが、Erlangポートに予期しない値が得られる)
だから、質問は:?私は大きな数字とプロトコルを動作させるために、あるいはフロートで何をすべき
はい、私は符号なしバイトが0から255であることを知っています。あなたが提供したリンクは私の質問で言及したチュートリアルのPDF版のようです。 – skanatek
それを読んで、バイトの範囲を理解しているなら、なぜバイトの範囲外の値が使えると期待していたのですか? – geekosaur
これらの値が1バイトの範囲外で動作するとは思わなかった。私はこの例がうまくいくことを知っていますが、私はそれを微調整したいと思います。問題は「プロトコルをより大きい数で、あるいは浮動小数点でも動作させるためにはどうすればよいでしょうか」でした。申し訳ありませんが私は十分に明確にしていない場合。 – skanatek