Kernel#putc vs. $stdout#putc

I was under the impression that Kernel#putc was an alias, or wrapper
around $stdout#putc, but I was mistaken. It turns out they’re both
implemented separately in C, and both pass to $stdout.write. I’m
trying to redefine putc in the Win32::Console::ANSI::IO object (in the
win32console gem), so that it buffers ANSI escape sequences and passes
them as a single unit. In order for this to work, I’ll have to
redefine Kernel#putc to use Win32::Console::ANSI::IO#putc like this:

module Kernel

def putc(int)
$stdout.putc(int)
end

end

Does anyone see a reason why this would be a bad idea? If so, any
other solutions?

Thanks,

Gordon

Hi:

On Thu, Feb 21, 2008 at 4:44 AM, Gordon T. [email protected]
wrote:

I was under the impression that Kernel#putc was an alias, or wrapper
around $stdout#putc, but I was mistaken. It turns out they’re both
implemented separately in C, and both pass to $stdout.write.

Not quite:

static VALUE
rb_f_putc(VALUE recv, VALUE ch)
{
return rb_io_putc(rb_stdout, ch);
}

Kernel#putc here passes to IO#putc anyway, which then (as you mention)
uses
IO#write.

Gordon

Arlen

On Wed, Feb 20, 2008 at 7:54 PM, Arlen C. [email protected] wrote:

OK, here’s why I’m confused. In the code below, why isn’t the output
of both of the putc methods 42?

class ChunkyIO < IO

def putc(int)
write ‘42’
end

end

$stdout = ChunkyIO.new(1,‘w’)

putc ?K
puts
$stdout.putc ?K
puts

#outputs
K
42

Hi,

On Fri, Feb 22, 2008 at 5:52 AM, Gordon T. [email protected]
wrote:

OK, here’s why I’m confused. In the code below, why isn’t the output
of both of the putc methods 42?

Here’s the relevant code from io.c:

static VALUE
rb_io_putc(VALUE io, VALUE ch)
{
char c = NUM2CHR(ch);

rb_io_write(io, rb_str_new(&c, 1));
return ch;

}

static VALUE
rb_f_putc(VALUE recv, VALUE ch)
{
return rb_io_putc(rb_stdout, ch);
}

As you can see, rb_f_putc (Kernel.putc) is hard-wired to rb_io_putc
(IO#putc) - but it’s directly hard-wired (I believe), not literally as
“$stdout.putc” but rather going straight to the function as defined
here.
This means that the two functions are ‘identical’ in nature –
Kernel.putcisn’t $stdout.putc, but rather will always call
rb_io_write(rb_stdout,
rb_str_new(&ch, 1)), which is $stdout.write with a string of that one
character.
Hence, you actually would have to redefine both ($stdout.putc, by your
ChunkyIO, and Kernel.putc) – or redefine $stdout.write (in which case
both functions will be affected) – in order to get the effect you want.

Cheers,
Arlen.