Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: reading/writing to stdout/stdin of another program?

Author: Rémi Coulom

Date: 01:36:02 05/23/02

Go up one level in this thread


On May 22, 2002 at 22:04:24, martin fierz wrote:

>aloha,
>
>i have written a checkers interface called "checkerboard" which uses dll's as
>checkers engines. since this approach is limited to windows, i would like to
>change things so that engines read and write to standard input and output and
>the interface reads and writes there. hmm - i just don't know how that is
>done... can somebody give me a tip? (can be very short, what kind of function
>that might be, i can then look it up in the f*** manuals).
>
>cheers
>  martin

How to do this depends on your system. If you are writing this in Windows, it is
very complicated. You can take a look at winboard, as Bob suggested. My
"wbengine" code might look simpler. I have appended my code to this message. You
can find the full source at my homepage: (that's wbengine/src/wbengine.cpp)
http://remi.coulom.free.fr/programs0046.tar.gz
(it would be two lines of code in Linux)

Rémi

////////////////////////////////////////////////////////////////////////////
// Start the child engine
////////////////////////////////////////////////////////////////////////////
void CWinboardEngine::StartChild()
{
 TerminateChild();

 //
 // Set the bInheritHandle flag so pipe handles are inherited.
 //
 SECURITY_ATTRIBUTES saAttr;
 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
 saAttr.bInheritHandle = TRUE;
 saAttr.lpSecurityDescriptor = 0;

 //
 // Redirect child process's STDOUT:
 //
 HANDLE hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
 {
  HANDLE hChildStdoutRd;
  CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0);
  SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr);
  DuplicateHandle(GetCurrentProcess(),
                  hChildStdoutRd,
                  GetCurrentProcess(),
                  &hChildStdoutRdDup ,
                  0,
                  FALSE,
                  DUPLICATE_SAME_ACCESS);
  CloseHandle(hChildStdoutRd);
 }

 //
 // Redirect child process's STDIN:
 //
 HANDLE hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
 {
  HANDLE hChildStdinWr;
  CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0);
  SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd);
  DuplicateHandle(GetCurrentProcess(),
                  hChildStdinWr,
                  GetCurrentProcess(),
                  &hChildStdinWrDup,
                  0,
                  FALSE,
                  DUPLICATE_SAME_ACCESS);
  CloseHandle(hChildStdinWr);
 }

 //
 // Now create the child process.
 //
 {
  STARTUPINFO siStartInfo;
  ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
  siStartInfo.cb = sizeof(STARTUPINFO);
  fHasChild = CreateProcess(0,
		            (char *)sCommandLine.c_str(), //???
                            0,
                            0,
                            TRUE,
                            0,
                            0,
                            sDirectory.c_str(),
                            &siStartInfo,
                            &piProcInfo);
 }

 //
 // After process creation, restore the saved STDIN and STDOUT.
 //
 SetStdHandle(STD_INPUT_HANDLE, hSaveStdin);
 SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
 if (fHasChild) {
  //
  // Engine initialization
  //
  SendToChild("xboard\n");
  SetPosition(GetPosition());

  //
  // Create the reader thread
  //
  ResetEvent(hLineProcessed);
  ResetEvent(hLineRead);
  fStopThread = 0;
  hThread = CreateThread(0, 0, ReaderThread, this, 0, &dwThread);
  if (!hThread)
   TerminateChild();
 }
}

////////////////////////////////////////////////////////////////////////////
// Close the reader thread and terminate the child engine
////////////////////////////////////////////////////////////////////////////
void CWinboardEngine::TerminateChild()
{
 if (fHasChild)
 {
  SendToChild("quit\n");
  CloseHandle(hChildStdinRd);
  CloseHandle(hChildStdoutWr);
 }

 if (hThread)
 {
  fStopThread = 1;
  SetEvent(hLineProcessed);
  WaitForSingleObject(hThread, INFINITE);
  CloseHandle(hThread);
  dwThread = 0;
 }

 if (fHasChild)
 {
  CloseHandle(hChildStdinWrDup);
  CloseHandle(hChildStdoutRdDup);
  TerminateProcess(piProcInfo.hProcess, 0);
  fHasChild = 0;
 }
}

////////////////////////////////////////////////////////////////////////////
// Send command to child
////////////////////////////////////////////////////////////////////////////
void CWinboardEngine::SendToChild(const char *psz)
{
 DWORD dwWritten;
 WriteFile(hChildStdinWrDup, psz, strlen(psz), &dwWritten, 0);
 InfoGeneral("<");
 InfoGeneral(psz);
}



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.