go - Converting Erlang-C port example to Erlang-Golang -
i'm trying write golang driver erlang, accesible via erlang port.
i've started erlang c port example, works fine:
http://www.erlang.org/doc/tutorial/c_port.html
now i'm trying port c code golang; trying echo simple 'hello world\n' message, using '\n' delimiter.
so golang code follows:
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) }
and can compile , run command line follows:
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
however when try call driver erlang side (erlang code below) following:
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 ^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'
i have sense message being passed ok driver, somehow returning response incorrectly.
tia.
erlang port code:
-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.
posting answer based on @justin's follow-up question here, contains different working answer.
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
:
-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 ^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"