【问题标题】:Communicating between a ruby script and a running c++ program在 ruby​​ 脚本和正在运行的 c++ 程序之间进行通信
【发布时间】:2010-02-18 12:55:56
【问题描述】:

我有一个执行一个功能的 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++ 程序员,所以谢谢你的帮助。

【问题讨论】:

    标签: c++ ruby sockets call


    【解决方案1】:

    一种可能的方法是修改您的 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()
    

    【讨论】:

      【解决方案2】:

      嗯,

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

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

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

      3) 如果您的 c++ 可以通过 c 头文件公开,那么使用 FFI 构建桥接器几乎是微不足道的。 Jeremy Hinegardner 在 ruby​​conf heresthe screencast 上做了一个关于构建 FFI 接口的精彩讲座@

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

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

      干杯!

      【讨论】:

        猜你喜欢
        • 2013-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-06
        • 1970-01-01
        相关资源
        最近更新 更多