当前位置: 首页 > 面试题库 >

将Erlang-C端口示例转换为Erlang-Golang

姬自强
2023-03-14
问题内容

我正在尝试为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

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"


 类似资料:
  • 问题内容: 我有一个简单的从Erlang到Golang的端口示例,将数据从Erlang传递到Golang并回显响应。 问题是我可以传输的数据量似乎限制为2 ^ 8字节(请参见下文)。我认为问题可能出在Golang端(没有创建足够大的缓冲区),但是用bufio.NewReaderSize替换bufio.NewReader无效。因此,我现在认为问题可能出在Erlang一方。 我该怎么做才能增加缓冲区大

  • Erlang RabbitMQ客户端无法工作...(http://www.RabbitMQ.com/erlang-client-user-guide.html) 以下是我采取的步骤。 已创建模块amqp_example.erl 已创建deps文件夹 将rabbit-common和amqp_client放在deps文件夹中 使用erl_libs=deps erlc-o ebin amqp_examp

  • 主要内容:算术运算符示例Erlang 语言支持正常的算术运算符类似于在其它语言中。以下是在 Erlang 中可用的算术运算符。 操作符 描述 示例 + 两个操作数相加 1 + 2 = 3 − 从第一个操作数减去第二个操作数 1 - 2 = -1 * 两个操作数相乘 2 * 2 = 4 / 通过分子除以分母 2 / 2 = 1 rem 第二数除以第一数的余数 3 rem 2 = 1 div div组件将执行除法并返回整数部

  • Erlang shell 被用于表达式的测试。因此,测试可以在 shell 进行,这是在实际的应用程序运行之前进行测试。 下面的例子展示了如何在 shell 中添加表达式并使用。这里需要指出的是,表达需要使用(.)定界符来作为结束符。 执行该命令后,shell 打印出另一个提示,此时为命令编号为2(因为指令数在每次输入新命令后增加)。 以下函数在 Erlang Shell 最常见的。 b() − 

  • Erlang 版本的 socket.io 服务器实现

  • maestro 是 Erlang 池管理程序。 为什么? 短暂 I/O 任务(比如数据库访问)的大型 worker 池会因为太多迁入和迁出活动而拖垮单个 poolboy 管理器。 怎样做? 使用简单的方法,启动多个池;随机迁出。maestro 需要了解每个池的工作流,当每个池都是同一类型的加载模式时,将会提升复杂性,降低性能,没有什么明显的优势。 使用: MaestroName = many_po