Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Aufruf einer UCI-Engine in Delphi (3) ?

Author: Lothar Hummel

Date: 11:53:07 04/07/04

Go up one level in this thread


On April 06, 2004 at 15:53:19, Andreas Herrmann wrote:

>On April 06, 2004 at 14:48:57, Lothar Hummel wrote:
>
>>On April 06, 2004 at 13:18:24, Andreas Herrmann wrote:
>>
>>>On April 06, 2004 at 13:09:53, Andreas Herrmann wrote:
>>>
>>>>On April 06, 2004 at 10:35:54, Lothar Hummel wrote:
>>>>
>>>>>
>>>>>Wie kann ich von einem in Delphi 3 geschriebenen Programm (also aus GUI-Sicht)
>>>>>eine UCI-Engine aufrufen ? Nach langer Suche habe ich nur den "shellexecute"
>>>>>gefunden, dann erscheint aber das aufgerufene Programm als eigenständiger Task
>>>>>unter Windows, ohne jede Verbindung zum aufrufenden Programm.
>>>>>
>>>>>Die Standard-Ein/Ausgabe gibts zwar auch in Delphi, sie funktioniert aber nur
>>>>>bei sogenannten "Konsolenanwendungen", eine GUI ist aber genau das Gegenteil
>>>>>davon. Kennt zufällig jemand eine konkrete Lösung für Aufruf und Datenaustausch
>>>>>?
>>>>
>>>>Hi,
>>>>
>>>>du solltest hier im Netz nach "Redirect standard input ouput" suchen. Da findest
>>>>du ein oder zwei C Beispiele im Netz, die du dann nach deinen Anforderungen
>>>>übersetzten und anpassen kannst. Du kannst aber z.B. auch in der Win API Hilfe
>>>>nach "CreatePipe","PeekNamedPipe" ... suchen und es selbst erarbeiten. Ev.
>>>>findest du auch etwas in der Microsoft MSDN dazu.
>>>>
>>>>Ich habe da letztes Jahr auch eine Delphi Komponente entwickelt. Falls du einige
>>>>Wochen warten kannst, findest du dann meine Delphi Komponente auf
>>>>http://wbholmes.de. Die momentane Version kann nur mit einem externen Prozess
>>>>kommunizieren und läuft auch noch nicht in einem separaten Thread. Sobald ich
>>>>Zeit habe werde ich die Komponente aber neu schreiben, damit auch die eben
>>>>beschriebenen Nachteile behoben sind.
>>>>
>>>>Andreas
>>>
>>>noch vergessen zu erwähnen: Anstatt ShellExecute mußt du CreateProcess
>>>verwenden. Siehe dazu vor allem auch unter LPSTARTUPINFO, da mußt du die
>>>Input/Output Handles entsprechend zuweisen.
>>>
>>>viel Erfolg
>>>Andreas
>>
>>hallo Andreas,
>>Danke erstmal für Deine Tips ! Den "createprocess" habe ich gefunden, allerdings
>>sind ja da unendlich viele Parameter mitzugeben ! Bei meiner Delphi-Version 3,
>>damals original in Deutsch gekauft (keine Raubkopie), ist zu Win api keinerlei
>>Dokumentation oder Hilfe beigefügt. Was man nicht erahnen kann, ist dann,
>>zumindest für mich, meist nicht anzuwenden. Gibts irgendwo Hilfe zu den ganzen
>>Windows-Schnittstellen ?
>>
>>Grüße, Lothar
>
>ich kann dir das folgende Buch dazu empfehlen:
>Delphi Win32 Lösungen
>Andreas Kosch
>Software & Support Verlag
>ISBN 3-9806738-2-0
>
>Das Buch behandelt u.a. auch verschiedene Möglichkeiten der Interprozess
>Kommunikation, wie z.B. Named Pipes.
>
>Im Entwickler Forum (http://www.entwickler.com/) hilft man dir bestimmt auch
>weiter. Der Author des obigen Buches beantwortet dort übrigens auch oft Fragen.
>
>Und noch etwas source code, den ich irendwo im Internet gefunden hatte, und der
>mir bei der Entwicklung der Delphi Komponente auch hilfreich war.
>
>
>Subject: How to create a process and control its flow by redirecting its
>standard input/output to your parent process.
>Introduction: In this article, I will explain how to spawn a console application
>and redirect its standard input/output using anonymous pipes. An anonymous pipe
>is a pipe that goes only in one direction (read pipe, write pipe, etc.). Maybe
>you are asking, "why would I ever need to do this sort of thing?" One example
>would be a Windows telnet server, where you spawn a shell and listen on a port
>and send and receive data between the shell and the socket client. (Windows does
>not really have a built-in remote shell).
>First, we should talk about pipes. A pipe in Windows is simply a method of
>communication, often between process. The SDK defines a pipe as "a communication
>conduit with two ends; a process with a handle to one end can communicate with a
>process having a handle to the other end." In our case, we are using "anonymous"
>pipes, one-way pipes that "transfer data between a parent process and a child
>process or between two child processes of the same parent process." It's easiest
>to imagine a pipe as its namesake. An actual pipe running between processes that
>can carry data.
>
>We are using anonymous pipes because the console app we are spawning is a child
>process. We use the CreatePipe function which will create an anonymous pipe and
>return a read handle and a write handle. We will create two pipes, on for stdin
>and one for stdout. We will then monitor the read end of the stdout pipe to
>check for display on our child process. Every time there is something availabe
>for reading, we will display it in our app. Consequently, we check for input in
>our app and send it off to the write end of the stdin pipe.
>
>Code: Sample app that spawns a shell and redirects its i/o
>//------------Sample using CreateProcess and Anonymous Pipes-----------------
>//---------------------childspawn.cpp----------------------------------------
>//---------------------use freely--------------------------------------------
>#include <windows.h>
>#include <stdio.h>
>#include <conio.h>
>#include <string.h>
>#pragma hdrstop
>#include <condefs.h>
>
>#define bzero(a) memset(a,0,sizeof(a)) //easier -- shortcut
>
>bool IsWinNT()  //check if we're running NT
>{
>  OSVERSIONINFO osv;
>  osv.dwOSVersionInfoSize = sizeof(osv);
>  GetVersionEx(&osv);
>  return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
>}
>
>void ErrorMessage(char *str)  //display detailed error info
>{
>  LPVOID msg;
>  FormatMessage(
>    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
>    NULL,
>    GetLastError(),
>    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
>    (LPTSTR) &msg,
>    0,
>    NULL
>  );
>  printf("%s: %s\n",str,msg);
>  LocalFree(msg);
>}
>
>//---------------------------------------------------------------------------
>void main()
>{
>  char buf[1024];           //i/o buffer
>
>  STARTUPINFO si;
>  SECURITY_ATTRIBUTES sa;
>  SECURITY_DESCRIPTOR sd;               //security information for pipes
>  PROCESS_INFORMATION pi;
>  HANDLE newstdin,newstdout,read_stdout,write_stdin;  //pipe handles
>
>  if (IsWinNT())        //initialize security descriptor (Windows NT)
>  {
>    InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
>    SetSecurityDescriptorDacl(&sd, true, NULL, false);
>    sa.lpSecurityDescriptor = &sd;
>  }
>  else sa.lpSecurityDescriptor = NULL;
>  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
>  sa.bInheritHandle = true;         //allow inheritable handles
>
>  if (!CreatePipe(&newstdin,&write_stdin,&sa,0))   //create stdin pipe
>  {
>    ErrorMessage("CreatePipe");
>    getch();
>    return;
>  }
>  if (!CreatePipe(&read_stdout,&newstdout,&sa,0))  //create stdout pipe
>  {
>    ErrorMessage("CreatePipe");
>    getch();
>    CloseHandle(newstdin);
>    CloseHandle(write_stdin);
>    return;
>  }
>
>  GetStartupInfo(&si);      //set startupinfo for the spawned process
>  /*
>  The dwFlags member tells CreateProcess how to make the process.
>  STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW
>  validates the wShowWindow member.
>  */
>  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
>  si.wShowWindow = SW_HIDE;
>  si.hStdOutput = newstdout;
>  si.hStdError = newstdout;     //set the new handles for the child process
>  si.hStdInput = newstdin;
>  char app_spawn[] = "d:\\winnt\\system32\\cmd.exe"; //sample, modify for your
>                                                     //system
>
>  //spawn the child process
>  if (!CreateProcess(app_spawn,NULL,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
>                     NULL,NULL,&si,&pi))
>  {
>    ErrorMessage("CreateProcess");
>    getch();
>    CloseHandle(newstdin);
>    CloseHandle(newstdout);
>    CloseHandle(read_stdout);
>    CloseHandle(write_stdin);
>    return;
>  }
>
>  unsigned long exit=0;  //process exit code
>  unsigned long bread;   //bytes read
>  unsigned long avail;   //bytes available
>
>  bzero(buf);
>  for(;;)      //main program loop
>  {
>    GetExitCodeProcess(pi.hProcess,&exit);      //while the process is running
>    if (exit != STILL_ACTIVE)
>      break;
>    PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
>    //check to see if there is any data to read from stdout
>    if (bread != 0)
>    {
>      bzero(buf);
>      if (avail > 1023)
>      {
>        while (bread >= 1023)
>        {
>          ReadFile(read_stdout,buf,1023,&bread,NULL);  //read the stdout pipe
>          printf("%s",buf);
>          bzero(buf);
>        }
>      }
>      else {
>        ReadFile(read_stdout,buf,1023,&bread,NULL);
>        printf("%s",buf);
>      }
>    }
>    if (kbhit())      //check for user input.
>    {
>      bzero(buf);
>      *buf = (char)getche();
>      //printf("%c",*buf);
>      WriteFile(write_stdin,buf,1,&bread,NULL); //send it to stdin
>      if (*buf == '\r') {
>        *buf = '\n';
>        printf("%c",*buf);
>        WriteFile(write_stdin,buf,1,&bread,NULL); //send an extra newline char,
>                                                  //if necessary
>      }
>    }
>  }
>  CloseHandle(pi.hThread);
>  CloseHandle(pi.hProcess);
>  CloseHandle(newstdin);            //clean stuff up
>  CloseHandle(newstdout);
>  CloseHandle(read_stdout);
>  CloseHandle(write_stdin);
>}
>//----------------------------EOF--------------------------------------------
>//---------------------------------------------------------------------------
>
>
>Gruß
>Andreas

hallo Andreas,

habe das Ganze in Delphi umgeschrieben und bei mir eingebaut und siehe da, es
funktioniert tadellos ! Danke nochmal, Du warst mir eine große Hilfe !

Gruß
  LOthar




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.