Почему _popen здесь работает, а boost :: process — нет?

У меня есть следующий рабочий код с помощью _popen, на окнах,

m_pGNUPlot = _popen("/gnuplot/bin/gnuplot.exe", "w");
fprintf(m_pGNUPlot, "set term win\n");
fprintf(m_pGNUPlot, "set term pngcairo\n");
fprintf(m_pGNUPlot, "plot \"\Data.txt\" using 1:2 notitle\n");
fprintf(m_pGNUPlot, "set output \"\Out.png\"\n");
fprintf(m_pGNUPlot, "replot\n");
fflush(m_pGNUPlot);

Но проблема в том, что окно cmd продолжает всплывать, и нет способа предотвратить это (Ссылка на сайт)
Итак, я пишу эквивалентный код в boost :: process

bp::pipe m_Write;
bp::environment env = boost::this_process::environment();
m_Plot = new bp::child("/gnuplot/bin/gnuplot.exe", bp::std_in < m_Write, env, boost::process::windows::hide);
m_Write.write("set term win\n", sizeof(char)*14);
m_Write.write("set term pngcairo\n", sizeof(char) * 19);
m_Write("plot \"\Data.txt\" using 1:2 notitle\n", sizeof(char)*35);
m_Write("set output \"\Out.png\"\n", sizeof(char)*22);
m_Write.write("replot\n", sizeof(char) * 8);

Итак, мой вопрос — эквивалентны ли два фрагмента кода? И если так, то почему второй может не работать?

1

Решение

У меня нет окон, поэтому я протестировал его на своей Linux-машине, немного упростив:

#include <boost/process.hpp>
#include <iostream>

namespace bp = boost::process;

int main() {
bp::opstream m_Write;
boost::filesystem::path program("/usr/bin/gnuplot");
bp::child m_Plot(program, bp::std_in = m_Write);

m_Write << "set term png\n";
m_Write << "set output \"Out.png\"\n";
m_Write << "plot \"Data.txt\" using 1:2 notitle\n";
m_Write.flush();
m_Write.pipe().close();

m_Plot.wait();
std::cout << "Done, exit code: " << m_Plot.exit_code() << "\n";
}

Печать:

Done, exit code: 0

И создал этот красивый образ из упрощенные данные:

Windows

В Windows используйте возможности Boost Filesystem path сделать путь:

boost::filesystem::path program("C:\\gnuplot\\bin\\gnuplot.exe");

Другие заметки

Если весь скрипт действительно исправлен, подумайте об использовании необработанного литерала:

m_Write << R"(set term png
set output "Out.png"plot "Data.txt" using 1:2 notitle)" << std::flush;
m_Write.pipe().close();
2

Другие решения

Да, спасибо, сехе! Ускорение мощно, но отсутствие учебных пособий и примеров затрудняет начало работы.

Да, итоговый рабочий код для меня —

bp::opstream m_Write; //output stream to pipe
boost::filesystem::path program("/gnuplot/bin/gnuplot.exe");
m_Plot = new bp::child(program, bp::std_in = m_Write, bp::windows::hide); //this solves the problem with _popen
m_Write << "set term png\n";
m_Write << "set term pngcairo\n";
m_Write << "set output \"" + ToPosixPath(sPath) + "\"\n"; //Notice how this works with std::string :)
m_Write << "plot  \"" + CreateTemp(X, Y) + "\" using 1:2 notitle\n";
m_Write << "exit\n";
m_Write.flush();
m_Write.pipe().close();

m_Plot->wait(); //boost doc states "The call to wait is necessary, to obtain it and tell the operating system, that no one is waiting for the process anymore."delete m_Plot;

Некоторые моменты-

  • В Windows exe, который поддерживает каналы в самом gnuplot.exe, тогда как в linux их два — gnuplot.exe и pgnuplot.exe.

  • Обязательно протестируйте свои скрипты в графическом интерфейсе, этот код молча завершается сбоем! Код возврата будет 0.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector