uruchamianie procesu potomnego, używanie pipe

0

Mam problem, staram się zrozumieć jak wykonać coś takiego,
mamy przykładowy kod:

 
#include <iostream>
using namespace std;

void main()
{
	int a;
	while(true)
	{
		cout << "podaj nastepna liczbe\n";
		cin >> a;
		cout << "podana liczba : " << a << endl;
	}
}

Jest on skompilowany do postaci .exe, teraz chciałbym utworzyć drugi plik, który uruchamia sobie tego exeka, i odczytuje jego standardowe wyjście i pisze do jego wejścia, czyli
Pseudokod:

uruchom tamto.exe
odczytaj wyjscie z tamto.exe
jeżeli "podaj nastepna liczbe" napisz: tamto czeka na liczbe
pobierz liczbe i wyślij do tamto.exe

Ma ktoś prosty przykład takiego wykorzystania? Szukam w googlach po pipe/ przekierowanie standardowego wejscia wyjscia, Popen itd, ale dalej jakoś nie moge takiego prostego przykładu napisać...

0

Exeka odpalasz funkcją CreateProcess, podając jej uchwyty na potoki i/o (pola hStdInput i hStdOutput struktury STARTUPINFO).

0

popen jest jednokierunkowy. Aby i czytać i pisać trzeba użyć CreateProcess (Windows) jak 0x666 pisał.
Na MSDN jest przykład:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx

0

To, co mi podaliście oczywiście już wcześniej znalazłem szukając samemu, mowie, ze dalej nie czaje, pokusił by się ktoś o napisanie najprostszego przykładu, bez obsługi błędów, bez nawet podawania parametru z nazwą pliku do uruchomienia?
Tutaj http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx jest strasznie rozbudowany przykład, który na wejściu chce plik tekstowy(?), podaje mu nazwę pliku tekstowego bez zawartości, czy z zawartością nazwy drugiego .exe do uruchomienia, i dalej nic z tego.

0

Trzeba kombinować samodzielnie, a nie czekać na gotowe. Krótki opis tego, co powinieneś zrobić:

  • stwórz potoki funkcją CreatePipe
  • wypełnij strukturę STARTUPINFO. Pisałem jak, zresztą masz przykład z linka.
  • odpal proces funkcją CreateProcess, podając w argumencie wypełnioną wcześniej strukturę STARTUPINFO.
  • Funkcjami ReadFile i WriteFile odbierasz i wysyłasz dane. Jako uchwyt do pliku podajesz stworzony wcześniej uchwyt do potoku. Oczywiście komunikacja odbywa się na poziomie binarnym, więc nie będzie tak prosto, jakbyś używał sformatowanych strumieni C/C++. Wprawdzie niektóre biblioteki C umożliwiają przestawienie potoków, ale nie zawsze to działa. Sensowniej byłoby zaimplementować własną wersję streambuf dla strumieni istream i ostream.

--- dodane ---

Przypomniało mi się, że kiedyś implementowałem streambuf właśnie na potrzebę obsługi zewnętrznych potoków:

class pipe_streambuff: public std::streambuf
{
private:
	char    m_gbuff[512];
	HANDLE  m_read_pipe;
	HANDLE  m_write_pipe;

protected:
	int underflow()
	{      
		DWORD chRead = 0;

		if(ReadFile(m_read_pipe, m_gbuff, sizeof(m_gbuff), &chRead, NULL) == TRUE)
		{
			setg(m_gbuff, m_gbuff, m_gbuff + chRead);
			return sgetc();
		}

		return EOF;
	}

	int overflow (int c = EOF)
	{
		DWORD cbWritten = 0;
		BOOL res = WriteFile(m_write_pipe, &c, 1, &cbWritten, NULL);
		setp(0, 0, 0);
		return res == TRUE ? 0 : -1;
	}

public:

	pipe_streambuff(HANDLE in_, HANDLE out_)
		:m_read_pipe(in_), m_write_pipe (out_)
	{
		setg(m_gbuff, m_gbuff, m_gbuff);
		setp(0, 0, 0);
	}
};

Użycie:

/* podłączam standardowe potoki, Ty będziesz musiał użyć tych stworzonych funkcją CreatePipe */
HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);

auto_ptr<pipe_streambuff> buf(new pipe_streambuff(stdIn, stdOut));

istream is(buf.get());
ostream os(buf.get());

int n;
is >> n;
os << n << "test\n";

1 użytkowników online, w tym zalogowanych: 0, gości: 1