• Advertisement
Sign in to follow this  

[SOLVED] How do basic applications communicate with each other?

This topic is 4245 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been wanting to know this for quite a while now: How do IDE's, like Dev-C++, receive output from applications, like MinGW "mingw32-make.exe"? How do they parse it (progress bar in compiling, line number of error, source file, etc)? My guess: When the IDE calls the compiler, it records data from the application and uses that (but that seems improbable); An I/O stream is established that the IDE records and the compiler uses, etc; A common file is established (I doubt this one) Is this concept similar on all other platforms, or do they have another way? Also, if there is a method, could I get the code in C++? EDIT: Forgot to mention, if you didn't notice it by MinGW, the platform I'm in is Windows. EDIT: Finally got my own small example to work. Hurrah. What it boils down to - The applications communicate by pipelines, and this communication is established by a parent process invoking the child process, setting the child's standard input, output, and error streams. In Windows, the main functions for this are: CreatePipe, SetHandleInformation, CreateProcess, and file I/O. In Unix, those lucky [people] get to use "fork()", and "pipe()". I really don't know why I just wrote this. [Edited by - deadimp on July 6, 2006 4:46:15 PM]

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
generally its done by redirecting stdout and stdin. (atleast in *nix)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
try reading up on pipes,

basically you need to use the pipe function to create pipes

int pipe(int filedes[2]); will set filedes[0] and filedes[1] to the pipes read and write end respectivly. then you can use fcntl to duplicate stdin or stdout

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
oh and you might need the dup2 function aswell

Share this post


Link to post
Share on other sites
I can't find "fork()" (or "pipe") in MinGW (well, in <unistd.h> and two other related headers), and I've seen it in the few exapmles I've looked at.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
hmm right, those are unix specific.

try looking at createprocess on msdn. (i would guess that dup2 and pipe are unix specific aswell then so you might need to get help from some windows dev)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
BOOL WINAPI CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);


the lpStartupInfo struct

typedef struct _STARTUPINFO { DWORD cb; LPTSTR lpReserved; LPTSTR lpDesktop; LPTSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;


has 3 handles at the end, one for stdin , one for stdout, and one for stderr, you can create an instance of that struct, set the hStdOutput handle to a handle created by your application and then read from it.

you need to set STARTF_USESTDHANDLES in dwFlags aswell.

Share this post


Link to post
Share on other sites
Well, I also have VC++, looked in the help manual, and found "_pipe", with different arguments, "_dup2" (same arg's), but no "fork". I'll look into "CreateProcess", but I really like the simplicity of the Unix stuff.

EDIT: Well, I looked into it, but it doesn't seem the same, and I haven't exactly gotten into any depth on OS process, threads, etc.
I'll keep on searching for examples.

EDIT (again): Didn't see your previous post... And didn't see the std handles when looking (/skimming) the startup struct. Need to look further into handles... Can you directly convert an "int" file id to "HANDLE"? Or do you need to use Windows to create it?

NOTE: Argh! Connection keeps on resetting!

Share this post


Link to post
Share on other sites
Well, I found a Windows tutorial on this in the MSDN, just need to go through it a few times, write my own small wrapper, and I'll be good (this was just a question for curiosity).

Is there any simple way to convert Windows file handles to standard file handles?

EDIT: Oh yeah, here's the link

[Edited by - deadimp on July 6, 2006 3:32:13 PM]

Share this post


Link to post
Share on other sites
In VC _get_osfhandle will return you the Windows handle corresponding to the C-runtime file descriptor (the "int" file id as you put it). Dev-C++ probably has a different way, you'll need to read the docs.

All of this stuff is completely non-standard in the eyes of C/C++. It's OS- and compiler-specific by it's very nature. Thus as you see every combination of OS and compiler does it a little bit differently.

Share this post


Link to post
Share on other sites
Well, I found "int _open_osfhandle(int*,int)" that does the reverse of that. Thanks! (Also located it in MinGW "io.h")

Share this post


Link to post
Share on other sites
Well, here's the working example I made (heavily based off of the example, made in MinGW):
main.cpp > main.exe
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <fcntl.h>
#include <io.h>

//RECUERDA: _open_osfhandle

struct {
struct IO {
HANDLE read,write;
} in, out;
} child;

struct PACKET {
int x, y, z;
};

int main() {
printf("Create handles...\n");
SECURITY_ATTRIBUTES att;
memset(&att,0,sizeof(att));
att.nLength=sizeof(att); att.bInheritHandle=true;
CreatePipe(&child.in.read,&child.in.write,&att,0); //In-Read,Write
SetHandleInformation(child.in.write,HANDLE_FLAG_INHERIT,0); //In-Write
CreatePipe(&child.out.read,&child.out.write,&att,0); //Out-Read,Write
SetHandleInformation(child.out.read,HANDLE_FLAG_INHERIT,0); //Out-Read
printf("Create child process...\n");
STARTUPINFO start;
memset(&start,0,sizeof(start));
start.cb=sizeof(start);
start.hStdError=start.hStdOutput=child.out.write;
start.hStdInput=child.in.read;
start.dwFlags=STARTF_USESTDHANDLES;
PROCESS_INFORMATION proc;
bool out;
if (CreateProcess(NULL,"test",NULL,NULL,true,0,NULL,NULL,&start,&proc)) {
CloseHandle(proc.hProcess); CloseHandle(proc.hThread);
}
else {
printf("Error");
getch(); exit(0);
}
//Write to:
PACKET data={0,25,34};
DWORD ret;
if (!WriteFile(child.in.write,&data,sizeof(data),&ret,NULL)) printf("Wot?\n");
CloseHandle(child.in.write);
//Read from:
CloseHandle(child.out.write);
#define BUFFER_LEN 4096
char buffer[BUFFER_LEN];
ret=1;
while (ret>0) {
ReadFile(child.out.read,buffer,BUFFER_LEN,&ret,NULL);
fwrite(buffer,ret,1,stdout);
}
printf("\nDone processing");
getch();
return 0;
}



test.cpp > test.exe
#include <windows.h>
#include <conio.h>
#include <stdio.h>

struct PACKET {
int x, y, z;
};

int main()
{
PACKET data;
printf("Processing data: ");
fread(&data,sizeof(data),1,stdin);
printf("x: %d, y: %d, z: %d\n",data.x,data.y,data.z);
}





NOTE: Yes, I know I'm using binary I/O.

[Edited by - deadimp on July 6, 2006 5:48:13 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement