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

时间:2010-02-18 12:55:57

标签: c++ ruby sockets call

我有一个执行一个功能的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 个答案:

答案 0 :(得分:6)

一种可能的方法是修改C ++程序,使其从标准输入流(std :: cin)而不是从命令行参数获取输入,并通过标准输出(std :: cout)返回其结果)而不是main的返回值。然后,您的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()

答案 1 :(得分:3)

那么,

你可以通过多种不同的方式来解决这个问题。

1)执行此操作的简单,可能是丑陋的方法是让您的c ++运行并间歇性地检查文件,让您的ruby脚本生成包含您的参数的所述文件。然后你的C ++程序会使用包含的参数将结果返回给你可以在你的ruby脚本中等待的结果文件......这显然是HACK TASTIC,但实现起来非常简单并且可以工作。

2)将您的c ++代码公开为ruby的c扩展。这并不像听起来那么难,特别是如果你使用RICE并且提供的hackie解决方案会少得多。

3)如果你的c ++可以通过c头文件公开,那么用FFI构建一个桥几乎是微不足道的。 Jeremy Hinegardner在rubyconf继承人the screencast

上发表了关于构建FFI接口的精彩讲座

4)D-Bus提供应用程序通信总线,您可以更改C ++应用程序以利用所述事件总线并使用ruby-dbus

从您的ruby传递消息

当然还有其他一千条路线......也许这些路线中的一个或另一个可能证明是可行的:)

干杯!