2015-04-23 13 views
15

Sto provando a scrivere un driver Golang per Erlang, accessibile tramite una porta Erlang.Conversione di esempio porta Erlang-C in Erlang-Golang

ho iniziato con l'esempio di porta Erlang C, che funziona bene:

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

Ora sto cercando di porto il codice C per Golang; semplicemente cercando di echo un semplice messaggio 'Hello World \ n', usando '\ n' come delimitatore.

Quindi il mio codice Golang è il seguente:

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) 
} 

E posso compilarlo ed eseguirlo dalla riga di comando come segue:

[email protected]:~/work/erlang_golang_port$ go build -o tmp/echo echo.go 
[email protected]:~/work/erlang_golang_port$ ./tmp/echo 
Enter text: hello 
hello 

Tuttavia quando provo a chiamare il pilota il lato Erlang (codice Erlang sotto) ottengo il seguente:

[email protected]:~/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' 

Ho la sensazione che il messag e viene passato OK al driver, ma in qualche modo sto restituendo la risposta in modo errato.

TIA.

codice del porto 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. 
+4

'ping/0' utilizza' call_port/1' per inviare un tupla nel processo porta come messaggio che viene quindi inviato alla porta. I dati effettivi inviati a una porta possono essere solo una lista di byte. – rvirding

+4

anche 'fmt.Print (" Inserisci testo: ")' 'scrive su stdout. Il testo scritto è inaspettato dal processo di erlang. – wldsvc

+0

@rvirding dovrebbe averlo notato; trasposto l'esempio C in modo errato. Lavori. Grazie. – Justin

risposta

5

questo distacco risposta sulla base di @ domanda di follow-up di Justin here, che contiene una risposta leggermente diversa, ma di lavoro.

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 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"