gui for gtp engines in c#, how?

For discussing go computing, software announcements, etc.
Post Reply
blade90
Lives with ko
Posts: 160
Joined: Thu Sep 02, 2010 11:16 am
Rank: KGS 2k
GD Posts: 0
KGS: blade90
Has thanked: 15 times
Been thanked: 11 times

gui for gtp engines in c#, how?

Post by blade90 »

I want to make a simple GUI for GTP engines in C#, because I'm learning C# and want to know this for curiosity.
But the problem is how can I start a engine in gtp mode, send commands to it and receive the output?
After hours of search and trying everything out I still wasn't able to do it.
This is all I found: http://www.codeproject.com/KB/cs/ProcessStartDemo.aspx
Those who know C# will realize that this does not work. Because it this method will always wait for the process to end before reading the output. Reading the output while it runs results in freezing the GUI.

Is it even possible in C#? If yes how? If not are there any tutorials or documentation for C++? (I only know basics about C++)
Is it possible to write a DLL in C++ that does sending commands and receive the output - and use it in a C# application?
msgreg
Lives with ko
Posts: 294
Joined: Sun Nov 13, 2011 10:58 am
GD Posts: 0
Universal go server handle: MSGreg
Has thanked: 47 times
Been thanked: 94 times

Re: gui for gtp engines in c#, how?

Post by msgreg »

You would have to start the program in another thread or use BeginOutputReadline for an asynchronous call.

Doing this as your first C# program is going to be a challenge unless you have threading experience from other languages or OSes.
Founder, Central Mississippi Go Club
Free tips and resources for clubs and teaching
Go Kit Club Pack - pack of 13x13 go sets for clubs
Go Tin - very portable go
blade90
Lives with ko
Posts: 160
Joined: Thu Sep 02, 2010 11:16 am
Rank: KGS 2k
GD Posts: 0
KGS: blade90
Has thanked: 15 times
Been thanked: 11 times

Re: gui for gtp engines in c#, how?

Post by blade90 »

It's not my first C# program, I already made a few but never something like threading and all this.
I used BeginOutputReadline but it does not work how I want, the problem is to send more then only one command to the engine.
The first command in my case sends "list_commands" to gnugo and receive the list.
The second command sends "showboard" but then it freezes, I made many changes and now it tells me "you cannot write in a closed TextWriter". That confuses me because the code is:

Code: Select all

StreamWriter Writer = Engine.StandardInput;
Writer.WriteLine(Command);
Writer.Close(); // Without this the command won't be send


Looks like I can't open it again until I restart the engine itself.
msgreg
Lives with ko
Posts: 294
Joined: Sun Nov 13, 2011 10:58 am
GD Posts: 0
Universal go server handle: MSGreg
Has thanked: 47 times
Been thanked: 94 times

Re: gui for gtp engines in c#, how?

Post by msgreg »

Try flush()

Post again with results or questions. You're on the right track.
Founder, Central Mississippi Go Club
Free tips and resources for clubs and teaching
Go Kit Club Pack - pack of 13x13 go sets for clubs
Go Tin - very portable go
blade90
Lives with ko
Posts: 160
Joined: Thu Sep 02, 2010 11:16 am
Rank: KGS 2k
GD Posts: 0
KGS: blade90
Has thanked: 15 times
Been thanked: 11 times

Re: gui for gtp engines in c#, how?

Post by blade90 »

msgreg wrote:Try flush()

Post again with results or questions. You're on the right track.

flush() does nothing, the engine never recives the command.
When I close my application then it sends the command, in other words as soon as TextWriter has been closed.
Rémi
Lives with ko
Posts: 170
Joined: Sat Jan 14, 2012 4:11 pm
Rank: KGS 4 kyu
GD Posts: 0
Has thanked: 32 times
Been thanked: 119 times
Contact:

Re: gui for gtp engines in c#, how?

Post by Rémi »

What you want to do is very complicated in Windows. Below is some C++ code I wrote to start a process and setup pipes for communication. I suppose C# has access to the same kind of Windows API.

Then you should use threads for I/O, which is also complicated.

Rémi

Code: Select all

 //
 // 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,
                            pszCommandLine,
                            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);
Post Reply