在Ruby脚本和正在运行的C++程序之间进行通信

4
我有一个执行一项功能的C++程序。它将一个大型数据文件加载到数组中,接收一个整数数组并在该数组中执行查找,返回一个单个整数。我目前是将每个整数作为参数调用该程序,如下所示:
$ ./myprogram 1 2 3 4 5 6 7

我还有一个 Ruby 脚本,我想让这个脚本利用 C++ 程序。 目前,我是这样做的。
Ruby 代码:
arguments = "1 2 3 4 5 6 7"
an_integer = %x{ ./myprogram #{arguemnts} }
puts "The program returned #{an_integer}" #=> The program returned 2283

这一切都运作正常,但我的问题是每次 Ruby 进行此调用时,C++ 程序都必须重新加载数据文件(超过 100MB)-非常缓慢,效率很低。如何重写我的 C++ 程序,仅加载一次文件,使我能够通过 Ruby 脚本进行多次查找而无需每次重新加载文件。使用套接字是否是明智的方法?将 C++ 程序编写为 Ruby 扩展?显然,我不是一位有经验的 C++ 程序员,所以感谢您的帮助。
2个回答

5
一种可能的方法是修改您的C++程序,使其从标准输入流(std::cin)中获取输入,而不是从命令行参数中获取,并通过标准输出(std::cout)返回其结果,而不是作为主函数的返回值。然后,您的Ruby脚本将使用popen来启动C++程序。
假设C++程序当前的样子是:
// *pseudo* code
int main(int argc, char* argv[])
{
    large_data_file = expensive_operation();

    std::vector<int> input = as_ints(argc, argv);
    int result = make_the_computation(large_data_file, input);

    return result;
}

它将被转换成类似于以下内容:

// *pseudo* code
int main(int argc, char* argv[])
{
    large_data_file = expensive_operation();

    std::string input_line;
    // Read a line from standard input
    while(std:::getline(std::cin, input_line)){
        std::vector<int> input = tokenize_as_ints(input_line);
        int result = make_the_computation(large_data_file, input);

        //Write result on standard output
        std::cout << result << std::endl;
    }

    return 0;
}

以下是 Ruby 脚本示例:

io = IO.popen("./myprogram", "rw")
while i_have_stuff_to_compute
    arguments = get_arguments()
    # Write arguments on the program's input stream
    IO.puts(arguments)
    # Read reply from the program's output stream
    result = IO.readline().to_i();
end

io.close()

3

嗯,

你可以采用多种不同的方式来实现这个目标。

1)一个简单但可能不太美观的方法是让你的C++程序定期检查一个文件,然后让你的Ruby脚本生成该文件并包含你的参数。你的C++程序将使用包含的参数返回结果到一个结果文件中,在你的Ruby脚本中等待该结果文件... 这显然是一种比较“hack”的方法,但它非常简单易行,并且可以工作。

2)将你的C++代码作为一个C扩展暴露给Ruby。这并不像听起来那么难,特别是如果你使用RICE,这将提供一个更少“hack”的解决方案。

3)如果你的C++可以通过C头文件公开,则几乎可以使用FFI构建桥接。Jeremy Hinegardner在rubyconf上做了一个关于构建FFI接口的好演讲,这里有屏幕录像

4)D-Bus提供了一个应用程序通信总线,你可以修改你的C++应用程序以利用该事件总线,并使用ruby-dbus从你的Ruby中传递消息。

当然还有许多其他方法... 或许其中一种或另一种方法可以证明是可行的 :)

干杯!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接