我正在尝试为Erlang编写Golang驱动程序,可通过Erlang端口访问。
我从Erlang C端口示例开始,该示例运行良好:
http://www.erlang.org/doc/tutorial/c_port.html
现在,我正在尝试将C代码移植到Golang。只是尝试使用“ \ n”作为分隔符来回显简单的“ Hello World \ n”消息。
所以我的Golang代码如下:
package main import ( "bufio" "fmt" "os" ) func main() { reader := bufio.NewReader(os.Stdin) fmt.Print("Enter text: ") bytes, _ := reader.ReadBytes('\n') os.Stdout.Write(bytes) }
我可以编译它并从命令行运行它,如下所示:
justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ go build -o tmp/echo echo.go justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ ./tmp/echo Enter text: hello hello
但是,当我尝试从Erlang端(下面的Erlang代码)调用驱动程序时,会得到以下信息:
justin@justin-ThinkPad-X240:~/work/erlang_golang_port$ erl Erlang R16B03 (erts-5.10.4) [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false] Eshell V5.10.4 (abort with ^G) 1> c(complex1). {ok,complex1} 2> complex1:start("./tmp/echo"). <0.41.0> 3> complex1:ping(). =ERROR REPORT==== 23-Apr-2015::08:56:47 === Bad value on output port './tmp/echo'
我感觉该消息已被正确传递给驱动程序,但是我不知何故返回了错误的响应。
TIA。
Erlang端口代码:
-module(complex1). -export([start/1, stop/0, init/1]). -export([ping/0]). -define(HELLO_WORLD, [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 46]). start(ExtPrg) -> spawn(?MODULE, init, [ExtPrg]). stop() -> complex ! stop. ping() -> call_port({ping, ?HELLO_WORLD++[10]}). 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, Msg}}, receive {Port, {data, Data}} -> Caller ! {complex, Data} end, loop(Port); stop -> Port ! {self(), close}, receive {Port, closed} -> exit(normal) end; {'EXIT', Port, _Reason} -> exit(port_terminated) end.
根据@Justin发布此答案,该问题包含略有不同但有效的答案。
echo.go:
echo.go
package main import ( "bufio" "os" ) func main() { for{ reader := bufio.NewReader(os.Stdin) bytes, _ := reader.ReadBytes('\n') os.Stdout.Write(bytes) } }
complex1.erl:
complex1.erl
-module(complex1). -export([start/1, stop/0, init/1]). -export([send/1]). start(ExtPrg) -> spawn_link(?MODULE, init, [ExtPrg]). stop() -> complex ! stop. send(Y) -> call_port({msg, Y}). call_port({msg, 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}, []), loop(Port). loop(Port) -> receive {call, Caller, Msg} -> Port ! {self(), {command, Msg++[10]}}, Data = receive_all(Port, 100), Caller ! {complex, Data}, loop(Port); stop -> Port ! {self(), close}, receive {Port, closed} -> exit(normal) end; {'EXIT', Port, Reason} -> exit({port_terminated, Reason}) end. receive_all(Port, Timeout) -> receive_all(Port, Timeout, []). receive_all(Port, Timeout, Buffer) -> receive {Port, {data, Data}} -> receive_all(Port, Timeout, [Data | Buffer]) after Timeout -> lists:flatten(lists:reverse(Buffer)) end.
$ erl
Erlang R16B02_basho8 (erts-5.10.3) [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] Eshell V5.10.3 (abort with ^G) 1> c(complex1). {ok,complex1} 2> complex1:start("go run echo.go"). <0.40.0> 3> complex1:send("asdhadlsjahdslahjdlhd"). "asdhadlsjahdslahjdlhd" 4> complex1:send("aksdghjakdsgalkdgaldsagdlkagdlkadg"). "aksdghjakdsgalkdgaldsagdlkagdlkadg"