Связь между скриптом ruby ​​и работающей программой на С ++ - PullRequest
4 голосов
/ 18 февраля 2010

У меня есть программа на С ++, которая выполняет одну функцию.Он загружает большой массив данных в массив, получает массив целых чисел и выполняет поиск в этом массиве, возвращая одно целое число.В настоящее время я вызываю программу с каждым целым числом в качестве аргумента, например:

$ ./myprogram 1 2 3 4 5 6 7

У меня также есть сценарий ruby, и я хотел бы, чтобы этот сценарий использовал программу c ++.В настоящее время я делаю это следующим образом.

Ruby Code:

arguments = "1 2 3 4 5 6 7"
an_integer = %x{ ./myprogram #{arguemnts} }
puts "The program returned #{an_integer}" #=> The program returned 2283

Это все работает правильно, но моя проблема в том, что каждый раз, когда ruby ​​делает этот вызов, программа на С ++ должнаперезагрузите файл данных (более 100 МБ) - очень медленно и очень неэффективно.

Как я могу переписать мою программу на c ++, загрузить файл только один раз, что позволяет мне делать много поисков через скрипт ruby, не перезагружая файл каждый раз.Будет ли разумно использовать сокеты?Написание программы на c ++ в качестве расширения для ruby?

Очевидно, я не опытный программист на c ++, поэтому спасибо за вашу помощь.

Ответы [ 2 ]

6 голосов
/ 18 февраля 2010

Возможный подход состоит в том, чтобы модифицировать вашу программу на 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()
3 голосов
/ 18 февраля 2010

Ну

Вы можете сделать это несколькими разными способами.

1) Простой, потенциально уродливый способ сделать это - запустить ваш c ++ и периодически проверять файл, чтобы ваш скрипт ruby ​​создавал указанный файл, содержащий ваши аргументы. Затем ваша программа на C ++ будет использовать содержащиеся в ней аргументы, возвращая свой результат в файл результатов, который вы можете ожидать в своем скрипте ruby ​​... Это, очевидно, HACK TASTIC, но его очень просто реализовать и он будет работать.

2) Представьте ваш код на C ++ как расширение c для ruby. Это не так сложно, как звучит, особенно если вы используете RICE , и это даст значительно меньше хакерских решений.

3) Если ваш c ++ может быть открыт через заголовочный файл c, тогда почти тривиально построить мост с использованием FFI. Джереми Хинегарднер прочитал хорошую лекцию по созданию интерфейсов FFI на rubyconf heres screencast

4) D-Bus предоставляет коммуникационную шину приложения, вы можете изменить свое приложение C ++, чтобы использовать преимущества указанной шины событий и передавать сообщения от вашего ruby, используя ruby-dbus

Есть, конечно, тысяча других маршрутов ... Может быть, один или другой из них может оказаться жизнеспособным:)

Ура!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...