将Erlang-C端口示例转换为Erlang-Golang。

huangapple go评论122阅读模式
英文:

Converting Erlang-C port example to Erlang-Golang

问题

我正在尝试为Erlang编写一个Golang驱动程序,通过Erlang端口进行访问。

我已经从Erlang C端口示例开始,它可以正常工作:

http://www.erlang.org/doc/tutorial/c_port.html

现在我正在尝试将C代码移植到Golang;只是尝试回显一个简单的“Hello World\n”消息,使用“\n”作为分隔符。

所以我的Golang代码如下:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. )
  7. func main() {
  8. reader := bufio.NewReader(os.Stdin)
  9. fmt.Print("Enter text: ")
  10. bytes, _ := reader.ReadBytes('\n')
  11. os.Stdout.Write(bytes)
  12. }

我可以编译并从命令行运行它,如下所示:

  1. justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ go build -o tmp/echo echo.go
  2. justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ ./tmp/echo
  3. Enter text: hello
  4. hello

然而,当我尝试从Erlang端调用驱动程序(下面是Erlang代码)时,我得到以下错误:

  1. justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ erl
  2. Erlang R16B03 (erts-5.10.4) [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false]
  3. Eshell V5.10.4 (abort with ^G)
  4. 1> c(complex1).
  5. {ok,complex1}
  6. 2> complex1:start("./tmp/echo").
  7. <0.41.0>
  8. 3> complex1:ping().
  9. =ERROR REPORT==== 23-Apr-2015::08:56:47 ===
  10. Bad value on output port './tmp/echo'

我感觉消息已经成功传递给驱动程序,但我以某种方式错误地返回了响应。

谢谢。

英文:

I'm trying to write a Golang driver for Erlang, accesible via an Erlang port.

I've started with the Erlang C port example, which works fine:

http://www.erlang.org/doc/tutorial/c_port.html

Now I'm trying to port the C code to Golang; just trying to echo a simple 'Hello World\n' message, using '\n' as the delimiter.

So my Golang code is as follows:

  1. package main
  2. import (
  3. &quot;bufio&quot;
  4. &quot;fmt&quot;
  5. &quot;os&quot;
  6. )
  7. func main() {
  8. reader := bufio.NewReader(os.Stdin)
  9. fmt.Print(&quot;Enter text: &quot;)
  10. bytes, _ := reader.ReadBytes(&#39;\n&#39;)
  11. os.Stdout.Write(bytes)
  12. }

And I can compile it and run it from the command line as follows:

  1. justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ go build -o tmp/echo echo.go
  2. justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ ./tmp/echo
  3. Enter text: hello
  4. hello

However when I try to call the driver from the Erlang side (Erlang code below) I get the following:

  1. justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ erl
  2. Erlang R16B03 (erts-5.10.4) [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false]
  3. Eshell V5.10.4 (abort with ^G)
  4. 1&gt; c(complex1).
  5. {ok,complex1}
  6. 2&gt; complex1:start(&quot;./tmp/echo&quot;).
  7. &lt;0.41.0&gt;
  8. 3&gt; complex1:ping().
  9. =ERROR REPORT==== 23-Apr-2015::08:56:47 ===
  10. Bad value on output port &#39;./tmp/echo&#39;

I have the sense that the message is being passed OK to the driver, but that I am somehow returning the response incorrectly.

TIA.

Erlang port code:

  1. -module(complex1).
  2. -export([start/1, stop/0, init/1]).
  3. -export([ping/0]).
  4. -define(HELLO_WORLD, [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 46]).
  5. start(ExtPrg) -&gt;
  6. spawn(?MODULE, init, [ExtPrg]).
  7. stop() -&gt;
  8. complex ! stop.
  9. ping() -&gt;
  10. call_port({ping, ?HELLO_WORLD++[10]}).
  11. call_port(Msg) -&gt;
  12. complex ! {call, self(), Msg},
  13. receive
  14. {complex, Result} -&gt;
  15. Result
  16. end.
  17. init(ExtPrg) -&gt;
  18. register(complex, self()),
  19. process_flag(trap_exit, true),
  20. Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
  21. loop(Port).
  22. loop(Port) -&gt;
  23. receive
  24. {call, Caller, Msg} -&gt;
  25. Port ! {self(), {command, Msg}},
  26. receive
  27. {Port, {data, Data}} -&gt;
  28. Caller ! {complex, Data}
  29. end,
  30. loop(Port);
  31. stop -&gt;
  32. Port ! {self(), close},
  33. receive
  34. {Port, closed} -&gt;
  35. exit(normal)
  36. end;
  37. {&#39;EXIT&#39;, Port, _Reason} -&gt;
  38. exit(port_terminated)
  39. end.

答案1

得分: 6

echo.go:

  1. package main
  2. import (
  3. "bufio"
  4. "os"
  5. )
  6. func main() {
  7. for {
  8. reader := bufio.NewReader(os.Stdin)
  9. bytes, _ := reader.ReadBytes('\n')
  10. os.Stdout.Write(bytes)
  11. }
  12. }

complex1.erl:

  1. -module(complex1).
  2. -export([start/1, stop/0, init/1]).
  3. -export([send/1]).
  4. start(ExtPrg) ->
  5. spawn_link(?MODULE, init, [ExtPrg]).
  6. stop() ->
  7. complex ! stop.
  8. send(Y) -> call_port({msg, Y}).
  9. call_port({msg, Msg}) ->
  10. complex ! {call, self(), Msg},
  11. receive
  12. {complex, Result} ->
  13. Result
  14. end.
  15. init(ExtPrg) ->
  16. register(complex, self()),
  17. process_flag(trap_exit, true),
  18. Port = open_port({spawn, ExtPrg}, []),
  19. loop(Port).
  20. loop(Port) ->
  21. receive
  22. {call, Caller, Msg} ->
  23. Port ! {self(), {command, Msg++[10]}},
  24. Data = receive_all(Port, 100),
  25. Caller ! {complex, Data},
  26. loop(Port);
  27. stop ->
  28. Port ! {self(), close},
  29. receive {Port, closed} ->
  30. exit(normal)
  31. end;
  32. {'EXIT', Port, Reason} ->
  33. exit({port_terminated, Reason})
  34. end.
  35. receive_all(Port, Timeout) -> receive_all(Port, Timeout, []).
  36. receive_all(Port, Timeout, Buffer) ->
  37. receive
  38. {Port, {data, Data}} ->
  39. receive_all(Port, Timeout, [Data | Buffer])
  40. after Timeout ->
  41. lists:flatten(lists:reverse(Buffer))
  42. end.

$ erl

  1. Erlang R16B02_basho8 (erts-5.10.3) [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
  2. Eshell V5.10.3 (abort with ^G)
  3. 1> c(complex1).
  4. {ok,complex1}
  5. 2> complex1:start("go run echo.go").
  6. <0.40.0>
  7. 3> complex1:send("asdhadlsjahdslahjdlhd").
  8. "asdhadlsjahdslahjdlhd"
  9. 4> complex1:send("aksdghjakdsgalkdgaldsagdlkagdlkadg").
  10. "aksdghjakdsgalkdgaldsagdlkagdlkadg"
英文:

Posting this answer based on @Justin's follow-up question here, which contains a slightly different but working answer.

echo.go:

  1. package main
  2. import (
  3. &quot;bufio&quot;
  4. &quot;os&quot;
  5. )
  6. func main() {
  7. for{
  8. reader := bufio.NewReader(os.Stdin)
  9. bytes, _ := reader.ReadBytes(&#39;\n&#39;)
  10. os.Stdout.Write(bytes)
  11. }
  12. }

complex1.erl:

  1. -module(complex1).
  2. -export([start/1, stop/0, init/1]).
  3. -export([send/1]).
  4. start(ExtPrg) -&gt;
  5. spawn_link(?MODULE, init, [ExtPrg]).
  6. stop() -&gt;
  7. complex ! stop.
  8. send(Y) -&gt; call_port({msg, Y}).
  9. call_port({msg, Msg}) -&gt;
  10. complex ! {call, self(), Msg},
  11. receive
  12. {complex, Result} -&gt;
  13. Result
  14. end.
  15. init(ExtPrg) -&gt;
  16. register(complex, self()),
  17. process_flag(trap_exit, true),
  18. Port = open_port({spawn, ExtPrg}, []),
  19. loop(Port).
  20. loop(Port) -&gt;
  21. receive
  22. {call, Caller, Msg} -&gt;
  23. Port ! {self(), {command, Msg++[10]}},
  24. Data = receive_all(Port, 100),
  25. Caller ! {complex, Data},
  26. loop(Port);
  27. stop -&gt;
  28. Port ! {self(), close},
  29. receive {Port, closed} -&gt;
  30. exit(normal)
  31. end;
  32. {&#39;EXIT&#39;, Port, Reason} -&gt;
  33. exit({port_terminated, Reason})
  34. end.
  35. receive_all(Port, Timeout) -&gt; receive_all(Port, Timeout, []).
  36. receive_all(Port, Timeout, Buffer) -&gt;
  37. receive
  38. {Port, {data, Data}} -&gt;
  39. receive_all(Port, Timeout, [Data | Buffer])
  40. after Timeout -&gt;
  41. lists:flatten(lists:reverse(Buffer))
  42. end.

$ erl

  1. Erlang R16B02_basho8 (erts-5.10.3) [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
  2. Eshell V5.10.3 (abort with ^G)
  3. 1&gt; c(complex1).
  4. {ok,complex1}
  5. 2&gt; complex1:start(&quot;go run echo.go&quot;).
  6. &lt;0.40.0&gt;
  7. 3&gt; complex1:send(&quot;asdhadlsjahdslahjdlhd&quot;).
  8. &quot;asdhadlsjahdslahjdlhd&quot;
  9. 4&gt; complex1:send(&quot;aksdghjakdsgalkdgaldsagdlkagdlkadg&quot;).
  10. &quot;aksdghjakdsgalkdgaldsagdlkagdlkadg&quot;

huangapple
  • 本文由 发表于 2015年4月23日 16:07:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/29817331.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定