stdout in embedded ruby in win32

Ask a Question related to Ruby, Design and Development.

  1. #1

    Default stdout in embedded ruby in win32

    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.

    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

    redisrected $stdout, $stderr in ruby code is not enough. I need to catch
    all backtrace when exceptions occurs.

    any ideas ?

    thierry wilmot Guest

  2. Similar Questions and Discussions

    1. How to create or modify an Excel file with embedded charts w/o Win32::OLE?
      I am creating a web application that creates custom excel workbooks containing embedded charts for users to download. I know Win32::OLE can do...
    2. Redirect stdout, stderr to file and stdout
      I have a small script that does some admin work for me. What I need to do now is not only have is display information to STDERR and STDOUT but...
    3. Embedded Ruby in a MSVC++ project?
      Hey all, I'm working on a project in MS Visual C++, unfortunately the code is completely tied to that environment and that IDE so I'm trapped. ...
    4. [BUG?] UTF8 ruby and win32 dir
      Does it help if you run with -K? (aka $-K) Dan
    5. Ruby on an embedded ARM processor
      On Sat, Jul 12, 2003 at 09:53:27AM +0900, Ben Giddings wrote: Since you're developing in C, presumably you have a cross-compiler? Why not just...
  3. #2

    Default Re: stdout in embedded ruby in win32

    On Thu, 11 Sep 2003 00:13:34 +0200, 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.
    >
    > 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
    >
    > redisrected $stdout, $stderr in ruby code is not enough. I need to catch
    > all backtrace when exceptions occurs.
    >
    > any ideas ?
    I once attempted to redirect *all* output from Ruby, but it was on unix.
    Things works different on windows. Later $defout and $deferr got added.

    Reading your post, it seem like you already have managed to redirect
    $stdout and $stderr ? Is this correct ?
    If so then you just have to redirect $defout and $deferr, and that should
    be it (I guess).

    --
    Simon Strandgaard


    Simon Strandgaard Guest

  4. #3

    Default Re: stdout in embedded ruby in win32

    On Thu, Sep 11, 2003 at 06:09:58AM +0900, thierry wilmot wrote:
    | 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

    Hello Thierry,

    In my experience, the results you describe above occur when you mix
    different C/C++ runtime libraries (which is far too easy to do
    accidently IMO).

    Take a look at
    [url]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdkintro/sdkintro/mixing_library_types.asp[/url]

    Best regards,

    --
    Zane Dodson
    [email]zdodson@zdodson.com[/email]

    Zane Dodson Guest

  5. #4

    Default Re: stdout in embedded ruby in win32

    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.

    --
    Nobu Nakada

    nobu.nokada@softhome.net Guest

  6. #5

    Default Re: stdout in embedded ruby in win32

    [email]nobu.nokada@softhome.net[/email] 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_HAN DLE));



    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

    Sean O'Dell Guest

  7. #6

    Default Re: stdout in embedded ruby in win32

    First , thanks all for your answers, ruby community is great !

    Simon Strandgaard : I try to redicrect $defout, $deferr, it no works
    better and Ruby interpetor tell me these variables will now be obslete.

    Zane Dodson : Ok, I think I have here a beginning of answer. I compile
    my app in debug mode and link it with msvcrt-ruby18.dll compiled in
    release mode. Dependency walker show me that my app mount msvcrtd.dll
    and msvcrt.dll for ruby's dll. I try to compile ruby in debug mode, and
    all seems to work fine. (I not find an easy way to compile ruby dll in
    debug, so I hack makefile.sub)

    Nobu Nakada : Yes, when using Ruby static lib you can call all core ruby
    functions in a more easiest way than in dll mode, but if you wanna use
    extensions like webrick or drd, you must first found dll/so used by
    there extensions and link them to your app. That a never ending story !



    Sean O'Dell wrote:
    > [email]nobu.nokada@softhome.net[/email] 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_HAN DLE));
    >
    >
    >
    > 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
    >
    thierry wilmot Guest

  8. #7

    Default Re: stdout in embedded ruby in win32

    On Fri, Sep 12, 2003 at 04:33:44AM +0900, thierry wilmot wrote:
    | First , thanks all for your answers, ruby community is great !
    |
    |<snip>
    |
    | Zane Dodson : Ok, I think I have here a beginning of answer. I compile
    | my app in debug mode and link it with msvcrt-ruby18.dll compiled in
    | release mode. Dependency walker show me that my app mount msvcrtd.dll
    | and msvcrt.dll for ruby's dll. I try to compile ruby in debug mode, and
    | all seems to work fine. (I not find an easy way to compile ruby dll in
    | debug, so I hack makefile.sub)
    |
    | <snip>

    What you state above is consistent with my experience. You need
    everything linked with the same runtime DLL. This means the
    executable and all dependent DLLs. As I understand it, Microsoft
    has provided 3 different libraries, each in 2 varieties (debug and
    non-debug), providing 6 different ways to link the C runtime with an
    executable or DLL. If an executable or any of its dependent DLLs is
    linked with more than one of these runtime libraries, disaster is
    generally the result.

    Here is another link you might find helpful on this very confusing
    topic.
    [url]http://support.microsoft.com/default.aspx?scid=kb;en-us;94248[/url]

    Best regards,

    --
    Zane Dodson
    [email]zdodson@zdodson.com[/email]

    Zane Dodson Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139