我正在try 为Erlang编写一个Golang驱动程序,可以通过Erlang端口访问.

我已经从Erlang C端口示例开始,它可以很好地工作:

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

现在,我正在try 将C代码移植到Golang;只是try echo 一条简单的"Hello World\n"消息,并使用"\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

但是,当我try 从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'

我感觉到消息传递给驱动程序是正常的,但不知何故我返回的响应不正确.

蒂娅.

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的后续问题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"

Go相关问答推荐

如何获得与cksum相同的CRC 32?

使用Gorm创建自定义连接表

Golang ==错误:OCI运行时创建失败:无法启动容器进程:exec:./" bin:stat./" bin:没有这样的文件或目录:未知

具有GRPC的RBAC(基于角色的访问控制)-网关生成的REST风格的API

如何预编译Golang标准库?

如何描述OpenAPI规范中围棋的数据类型.JSON?

创建服务时云运行触发器执行失败

错误&对象已被Golang在K8s操作符上修改

如何使用gopher-lua定义一个Lua函数,该函数有一个预定义的表作为param,Lua脚本可以在其中访问该函数中的表?

为什么要立即调用内联函数,而不仅仅是调用其包含的函数?

运行 Docker 容器 - X11 无法打开显示:0

上传图片失败,出现错误dial tcp: lookup api.cloudinary.com: no such host

Go gmail api 快速入门导致本地主机拒绝连接 ERR_CONNECTION_REFUSED

处理程序后访问 HTTP 请求上下文

Golang invopop jsonschema 使用 if/then/else

go:识别重新定义标志的包

Go 导入范围查找 protobuf 类型

try 执行`go test ./... -v`时,Golang中有没有办法设置标志

如何允许可转换为指针的泛型类型参数化另一种可转换为指针的泛型类型?

在 etcd 键值存储中禁用历史记录