From: "Sean O'Dell" Date: 2003-09-11T12:31:16+09:00 Subject: Re: stdout in embedded ruby in win32 nobu.nokada@softhome.net wrote: > Hi, > > At Thu, 11 Sep 2003 06:09:58 +0900, > thierry wilmot wrote: > >>I have just finished to convert my ruby embedded app from static ruby >>lib (msvcrt-ruby18-static.lib) to dll, and have some problems with >>standard stream stdin,stdout,stderr redirection in dll mode. My .exe is >>not compile in console mode, but in windows mode. > > > Link with msvcrt.dll. > > >>a well works code in static lib : >> >> freopen("stdout.txt","w+",stdout); >> >>Does not work in dll mode, cause some unobvious Windows reasons a dll >>have it own std streams, and if your freopen() streams in .exe, they >>will not be redirected in the msvcrt-ruby18.dll > > > Due to the specification of Windows DLL. And if you want to > use extension libraries, you have to use ruby DLL or recompile > all libraries to import symbols from your .exe. Not sure if this solves your problem Thierry, but here's what I did in my Windows application to "capture" stdio streams used by the Ruby DLL: First, in the Ruby .dll, I hacked in these functions: int rb_w32_redirect_stdin(HANDLE pipe) { return dup2(_open_osfhandle((long)pipe, _O_TEXT), 0); } int rb_w32_redirect_stdout(HANDLE pipe) { return dup2(_open_osfhandle((long)pipe, _O_TEXT), 1); } int rb_w32_redirect_stderr(HANDLE pipe) { return dup2(_open_osfhandle((long)pipe, _O_TEXT), 2); } .... and exported them. Then in my application, I call: // thread that continually grabs Ruby's stdout output unsigned long __stdcall stdioReadThread(void* parameter) { DWORD dwRead; char chBuf[READ_THREAD_BUFFER_SIZE]; for( ;; ) { if(!ReadFile(stdioReadHandle, chBuf, READ_THREAD_BUFFER_SIZE - 1, &dwRead, NULL) || dwRead == 0) break; chBuf[dwRead / sizeof(char)] = '\0'; // DO SOMETHING WITH THE BUFFER HERE } return 0; } // create pipe that replaces Ruby's stdout if(CreatePipe(&stdioReadHandle, &stdioWriteHandle, NULL, 0)) { dup2(_open_osfhandle((long)stdioWriteHandle, _O_TEXT), 1); dup2(_open_osfhandle((long)stdioWriteHandle, _O_TEXT), 2); stdioReadThreadHandle = CreateThread(NULL, 0, stdioReadThread, outputTextBox, 0, &stdioReadThreadID); } // then call init, and re-assign Ruby's stdout handle ruby_init(); rb_w32_redirect_stdout(GetStdHandle(STD_OUTPUT_HANDLE)); The read thread will basically "sleep" on the pipe until Ruby sends output to the stdout handle. When it wakes up, it starts pulling from the pipe. The example above basically does nothing, but in my application, I sent the output to a textbox to simulate an output console. You could modify the read thread to do whatever you want with the output. Hope that helps ... someone ... Sean O'Dell