2017-05-18 32 views
2

我正在編寫一個教程,因爲我無法在任何地方找到一個簡單的例子,通過一個端口在Elixir和Rust之間進行通信。使用Elixir通過Ports與Rust交談,我發生了什麼問題?

我可以讓Rustler工作,但這是一個NIF,而不是一個端口。

我在代碼中缺少一些基本的東西。我不確定是否在stdio中缺少基本的東西,或者它是其他東西,但我嘗試了很多不同的東西。

可以得到端口通信魯斯特一個非常基本的程序協同工作:

defmodule PortExample do 

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

use std::env; 

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

我能得到這個被拉入我的IEX -S運行此端口混合

下面是用於該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)> 

然而,當我開始使用防鏽庫某種形式的輸入/輸出,事情開始翻倒。

例如,鏽代碼:

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 

然而,當我把它從藥劑端口:

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中的緩衝區。 我想:也許這個循環是懸掛的,所以我將它限制在只有幾次通過。 當我嘗試通過瓷器調用運行相同的代碼時,它掛起。

回答

4

您正在讀取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 
+0

謝謝!而已。我知道這一定是我失蹤的根本原因。 – aeroegnr

相關問題