Как продолжить выполнение кода C++ после вызова gnuplot?

Я использую gcc в качестве компилятора и gnuplot-iostream.h в качестве потока для объединения кода C++ и функций gnuplot.

Что я делаю:

Я пытаюсь привести данные в соответствие с помощью gnuplot и извлечь окончательные параметры соответствия из сгенерированного файла fit.log для дальнейшей обработки.

В чем проблема:

При выполнении кода, подобного этому

std::cout << "Starting to fit" << std::endl;
if (bStartFit == true)
{
    // gp << doing stuf here;
    std::cout << "Test end" << std::endl;
}
std::cout << "Fit is done" << std::endl;

вывод будет:

Starting to fit
Fit is done
Test end
//gnuplot stuff 

Мой вопрос: как заставить код выполнять вещи gnuplot именно тогда, когда это необходимо, и после продолжения работы с кодом C++. Например:

  • написать вступительное сообщение;
  • построить функцию sin(x) (как быстрый пример);
  • дождитесь закрытия gnuplot;
  • напишите выходящее сообщение или сделайте то, что когда-либо ПОСЛЕ gnuplot.

спасибо, P

РЕДАКТИРОВАТЬ:

  std::string filename = "fit.log";
  if (bStartFit == true)
  {
    // Using Gnuplot for the data fit (command are parsed as the strings):
    // 1. define the fit function.
    gp << "f(x) = imfpZP * x**(-b) + c * x**(d) + g * x**(h) \n";
    // 2. fit parameters first assumption.
    gp << "b = 1.1; c = 0.5; d = 1.0; g = 2.0; h = 0.1 \n";
    // 3. fit range.
    gp << "fit [50:10000] f(x) 'agn.iimfp' via b,c,d,g,h \n";
    // 4. set the logarithmic scale.
    gp << "set logscale \n";
    // 5. plot the fitted data.
    gp << "plot 'agn.iimfp' w l lw 2 tit 'orig', f(x) w l lw 2 tit 'fit' \n";

    std::cout << "Fit was successful" << std::endl;
  }

  // Opening the generated fit.log file to store the fit parameters:
  std::ifstream inFIT(filename.c_str());
  if (inFIT.is_open())
  {
    std::cout << "FIT log is opened" << std::endl;

    std::string line;
    int lineCounter = 0;
    while (std::getline(inFIT, line))
    {
      lineCounter++;
    }
    std::cout << "Total lines: " << lineCounter << std::endl;

    // Getting the five lines with fit parameters from the fit.log:
    std::fstream& GoToLine(std::fstream& file, unsigned int lineNumber);
    std::fstream file(filename.c_str());


    GoToLine(file, lineCounter - 15);
    std::string b_Line;
    std::getline(file, b_Line);
    std::cout << b_Line << std::endl;
    std::istringstream sb(b_Line);
    std::string tempStr;
    char tempChar;
    sb >> tempStr >> tempChar  >> b
    // similar code to get another 4 lines

;

1 ответ

Решение

Это зависит от операционной системы. Я предполагаю, что вы работаете в Linux (или, по крайней мере, в некоторых операционных системах POSIX). Тогда вам действительно стоит прочитать http://advancedlinuxprogramming.com/. И использование strace(1) может помочь понять, что происходит.

Вы можете использовать popen (3), но вам, вероятно, следует явно использовать системные вызовы (они перечислены в syscalls (2)), такие как pipe (2), fork (2), dup2 (2), execve (2), waitpid (2).) и т. д. И, скорее всего, есть некоторый цикл обработки событий (например, вокруг poll (2)).

Кстати, вы должны знать, что входной вывод буферизован, и вы, вероятно, хотите быть уверены, что ваш поток gnuplot регулярно сбрасывается (поэтому используйте std::endl или же std::flush соответственно на это). Написание \n недостаточно! Вы, вероятно, должны хотя бы кодировать

gp << "plot 'agn.iimfp' w l lw 2 tit 'orig', f(x) w l lw 2 tit 'fit' " 
   << std::endl;

(Я заменил некоторые \n внутри строки с явным использованием std::endl )

Я не знаю много о потоке gnuplot (полагаю, это немного похоже на специализированный popen но используя потоки C++), но я думаю, что вы должны gnuplot print или же printerr Команда сообщить вашей вызывающей программе тот факт, что данная кривая была построена. (Но тогда вам нужен подлинный цикл обработки событий, и вы определяете двунаправленный протокол между gnuplot и ваша программа.).

Возможно, Qt или POCO могут быть актуальны, потому что они предоставляют некоторое представление о цикле событий и процессах. Возможно, у вас может быть несколько потоков (один управляющий gnuplot а другой для отдыха), но тогда у вас есть проблемы с синхронизацией.

(Я недостаточно понимаю, что должна делать ваша программа и как вы ее закодировали, так что это слепое предположение; я чувствую, что ваш вопрос очень неясен)

Узнайте больше о межпроцессных коммуникациях.

Другие вопросы по тегам