gpt4 book ai didi

rust - 使用 Elixir 通过 Ports 与 Rust 对话,我哪里出错了?

转载 作者:行者123 更新时间:2023-11-29 07:58:07 25 4
gpt4 key购买 nike

我正在编写教程,因为我在任何地方都找不到通过端口在 Elixir 和 Rust 之间进行通信的简单示例。

我可以让 RuSTLer 工作,但那是 NIF,不是 Port。

我的代码中遗漏了一些基本的东西。我不确定我是否遗漏了 stdio 中的一些基本内容,或者是否还有其他内容,但我已经尝试了很多不同的东西。

可以让端口通信与 Rust 中的一个非常基本的程序一起工作:

use std::env;

fn main() {
println!("hello world!");
}

我可以通过运行此端口将它拉入我的 iex -S 混合:

defmodule PortExample do

def test() do
port = Port.open({:spawn_executable, "_build/dev/rustler_crates/portexample/debug/portexample"}, [:binary])
Port.info(port)
port
end

这是 iex 的样子:

Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> PortExample.test()
#Port<0.9420>
iex(2)> flush()
{#Port<0.9420>, {:data, "hello world!\n"}}
:ok
iex(3)>

我可以使用陶瓷库调用来做同样的事情:

  alias Porcelain.Result
def porcelain() do
result = Porcelain.exec("_build/dev/rustler_crates/portexample/debug/portexample",["hello", "world"])
IO.inspect result.out
end

对应的iex:

iex(3)> PortExample.porcelain()
"hello world!\n"
"hello world!\n"
iex(4)>

但是,一旦我开始使用具有某种形式的输入/输出的 Rust 库,事情就开始变得糟糕了。

例如,Rust 代码:

use std::io::{self, Write, Read};

fn main() {
let mut input = String::new();
let mut output = String::new();
for i in 0..2 {
match io::stdin().read_line(&mut input) {
Ok(n) => {
println!("input: {}", input.trim());
io::stdout().flush();
}
Err(error) => println!("error: {}", error),
}
}
}

我可以让它在命令行中编译和运行:

hello
input: hello
world
input: hello
world

但是,当我从 Elixir 端口调用它时:

iex(12)> port = PortExample.test()
#Port<0.8779>
iex(13)> Port.command(port, "hello")
true
iex(14)> Port.command(port, "world")
true
iex(15)> Port.command(port, "!")
true
iex(16)> Port.command(port, "more")
true
iex(17)> flush()
:ok
iex(18)> Port.info(port)
[name: '_build/dev/rustler_crates/portexample/debug/portexample',
links: [#PID<0.271.0>], id: 4697, connected: #PID<0.271.0>, input: 0,
output: 15, os_pid: 21523]

我根本没有得到任何数据!但是,Port.info(port) 调用显示它收到了 15 个字节。它只是没有将任何返回的东西发布到端口。我一直在尝试阅读其他代码,我认为我正在做足够相似的事情,它应该可以工作,但事实并非如此。

我想:也许缓冲区没有被刷新?所以我用 Rust 刷新缓冲区。我想:也许循环挂了,所以我将它限制为只有几次通过。当我尝试通过 porcelain 调用运行相同的代码时,它挂起了。

最佳答案

你正在读取 Rust 代码中的一行输入,它将读取到 \r\n\n,但你没有发送来自 Elixir 的换行符。如果您更改所有 Port.command 调用以在消息后添加 \n,它会起作用:

iex(1)> port = Port.open({:spawn_executable, "a"}, [:binary])
#Port<0.1229>
iex(2)> Port.command(port, "hello")
true
iex(3)> flush()
:ok
iex(4)> Port.command(port, "hello\n")
true
iex(5)> flush()
{#Port<0.1229>, {:data, "input: hellohello\n"}}
:ok

关于rust - 使用 Elixir 通过 Ports 与 Rust 对话,我哪里出错了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44050019/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com