2015-04-23 46 views
15

我想爲Erlang編寫Golang驅動程序,通過Erlang端口訪問。將Erlang-C端口示例轉換爲Erlang-Golang

我已經開始與二郎I2C端口例如,工作正常:

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

而且我可以編譯它,並在命令行中運行它,如下所示:

[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 

然而,當我嘗試調用從驅動程序在Erlang方面(Erlang代碼如下)我得到以下內容:

[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' 

我有這樣的感覺, e被傳遞給驅動程序,但是我不知何故錯誤地返回了響應。

TIA。

二郎口代碼:

-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

'平/ 0'使用'call_port/1'到元組發送到所述端口過程爲消息然後發送到端口。發送到端口的實際數據只能是一個字節列表。 – rvirding

+4

也'fmt.Print(「輸入文本:」)''寫入標準輸出。 erlang過程中寫入的文本是意料之外的。 – wldsvc

+0

@rvirding應該已經發現,錯誤地調換了C示例。作品。謝謝。 – Justin

回答

5

發佈基於@賈斯汀的後續問題here,其中包含一個略有不同,但工作回答這個問題的答案。

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"