Mac GUI source?

Discussion of chess software programming and technical issues.

Moderator: Ras

MikeAtBookup
Posts: 8
Joined: Fri Jun 14, 2013 7:45 pm

Mac GUI source?

Post by MikeAtBookup »

Is there any sample source of a Macintosh GUI available showing how to crank up an engine and start the UCI conversation?
Mike Leahy
www.bookup.com
User avatar
hgm
Posts: 28454
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Mac GUI source?

Post by hgm »

I thought this was just like in Linux. At least in XBoard it is. Normal fork() and pipe() calls.
AlvaroBegue
Posts: 932
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: Mac GUI source?

Post by AlvaroBegue »

hgm wrote:I thought this was just like in Linux. At least in XBoard it is. Normal fork() and pipe() calls.
Yes, on POSIX (read "non-Windows") systems these things are fairly standard.
User avatar
Evert
Posts: 2929
Joined: Sat Jan 22, 2011 12:42 am
Location: NL

Re: Mac GUI source?

Post by Evert »

hgm wrote:I thought this was just like in Linux. At least in XBoard it is. Normal fork() and pipe() calls.
Indeed. That's what I use for Sjef as well.
User avatar
hgm
Posts: 28454
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Mac GUI source?

Post by hgm »

So the UCI2WB source is probably the simplest source that meets your requirements.
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Mac GUI source?

Post by lucasart »

MikeAtBookup wrote:Is there any sample source of a Macintosh GUI available showing how to crank up an engine and start the UCI conversation?
As pointed out by others, the basic idea is fork() and exec(). However, in practice it's a lot more complicated than that, and you aldo need to create some pipes, and connect each end of the pipes to the right process and file descriptor.

Anyway, here's a sample C code, that basically does all you want. I've only tested it on Linux, but it should work on any POSIX compliant OS (ie. everything except Windows):

process.h

Code: Select all

#pragma once
#include <stdbool.h>
#include <stdio.h>
#include "unistd.h"

typedef struct {
   pid_t pid;
   FILE *in, *out;
} Process;

bool process_create(Process *p, const char *cmd);
bool process_destroy(Process *p);

bool process_readln(const Process *p, char *buf, size_t n);
bool process_writeln(const Process *p, char *buf);
process.c

Code: Select all

#include "process.h"
#include <sys/types.h>
#include <signal.h>

bool process_create(Process *p, const char *cmd)
{
   int readpipe[2], writepipe[2];
   #define PARENT_READ      readpipe[0]
   #define CHILD_WRITE      readpipe[1]
   #define CHILD_READ      writepipe[0]
   #define PARENT_WRITE   writepipe[1]

   if (pipe(readpipe) < 0 || pipe(writepipe) < 0)
      return false;

   p->pid = fork();
   
   if (p->pid == 0) {
      // in the child process
      close(PARENT_WRITE);
      close(PARENT_READ);

      if (dup2(CHILD_READ, STDIN_FILENO) == -1)
         return false;
      close(CHILD_READ);

      if (dup2(CHILD_WRITE, STDOUT_FILENO) == -1)
         return false;
      close(CHILD_WRITE);

      if (execlp(cmd, cmd, NULL) == -1)
         return false;
   }
   else if (p->pid > 0) {
      // in the parent process
      close(CHILD_READ);
      close(CHILD_WRITE);

      if (!(p->in = fdopen(PARENT_READ, "r")))
         return false;

      if (!(p->out = fdopen(PARENT_WRITE, "w")))
         return false;
      
      setvbuf(p->in, NULL, _IONBF, 0);
      setvbuf(p->out, NULL, _IONBF, 0);
   } else
      // fork failed
      return false;
   
   return true;
}

bool process_destroy(Process *p)
{
   // close the parent side of the pipes
   fclose(p->in);
   fclose(p->out);
   
   // kill the child process
   return kill(p->pid, SIGKILL) >= 0;
}

bool process_readln(const Process *p, char *buf, size_t n)
{
   return fgets(buf, n, p->in) >= 0;
}

bool process_writeln(const Process *p, char *buf)
{
   return fputs(buf, p->out) >= 0;
} 
Sample conversation (going through the uci->uciok introduction)

Code: Select all

#include <process.h>
#include <string.h>

int main(int argc, char **argv)
{
   Process p;
   process_create(&p, "/home/lucas/Chess/DC/DC");
   
   char buf[0x100];
   process_writeln(&p, "uci\n");
   
   while (true) {
      process_readln(&p, buf, sizeof(buf));
      printf(buf);
      if (!strcmp(buf, "uciok\n"))
         break;
   }
   
   process_destroy(&p);
} 
This library is a good starting point, although you can refine it in a few ways. One thing you may eventually need is a timed out read from the engine (if time out then the engine is considered hanging and something needs to be done in the GUI). You can use the POSIX function select() for that, or you can use threads.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Mac GUI source?

Post by lucasart »

I've just realized that all the answers so far assumed that you are programming in C or C++. If you program in Python for example, it's completely trivial to write this in a portable way, using the subprocess module. Other programming languages may have facilities to do that in their standard library.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
MikeAtBookup
Posts: 8
Joined: Fri Jun 14, 2013 7:45 pm

Re: Mac GUI source?

Post by MikeAtBookup »

I may be missing something basic here but the suggested source code seems to be aimed at Linux and/or Windows. I have similar code running in my Windows apps (Chess Openings Wizard, MasterChess).

Is the code to launch a child process and link to it really the same on the Macintosh?
Mike Leahy
www.bookup.com
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: Mac GUI source?

Post by sje »

MikeAtBookup wrote:Is the code to launch a child process and link to it really the same on the Macintosh?
Mac OS/X is based on OpenBSD, and that's very close to Linux. So the basic fork() and exec() stuff is the same. Actually, it's nearly the same as the early Unixes of the 1970s.

The thing here that's very different between Mac OS/X and Linux is that the Macs use the Quartz image engine and window manager while Linux uses X Windows and one of several different window managers.

While Mac OS/X can run X Windows, (and this is necessary to run xboard on a Mac), not every Mac user has X Windows installed.
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Mac GUI source?

Post by lucasart »

MikeAtBookup wrote:I may be missing something basic here but the suggested source code seems to be aimed at Linux and/or Windows. I have similar code running in my Windows apps (Chess Openings Wizard, MasterChess).

Is the code to launch a child process and link to it really the same on the Macintosh?
I said POSIX!

How could I have made myself clearer than that:
it should work on any POSIX compliant OS (ie. everything except Windows)
??
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.