Hi all,
I hope there is a guru out there today.
I create a new Pipe on Windows using 'CreatePipe'. This yields two
handles (for input and output) which can be converted to C run-time file
handles with _open_osfhandle. I can call fdopen on the returned values
and write and read to the pipe.
What I wanted to do was creating new IO objects instead of calling
fdopen myself, but I can't get it to work. The implementation of IO.new
calls fdopen so I realy have no clue why this should not do the trick.
(Yes I can call IO.pipe, but I need the handles from CreatePipe because
CreateProcess needs them and this is the only way to start childs
without unwanted shell windows)
The other way would be to write a C extension but I'm so close....
please help
Simon
···
---------------------------------------------------------------
require 'Win32API'
SECURITY_ATTRIBUTES_SIZE = 12
O_RDONLY = 0x0000 # open for reading only
O_WRONLY = 0x0001 # open for writing only
O_TEXT = 0x4000 # file mode is text (translated)
O_BINARY = 0x8000 # file mode is binary (untranslated)
def create_pipe # returns read and write handle
params = [
'P', # pointer to read handle
'P', # pointer to write handle
'P', # pointer to security attributes
'L'] # pipe size
createPipe = Win32API.new("kernel32", "CreatePipe", params, 'I')
read_handle, write_handle = [0].pack('I'), [0].pack('I')
sec_attrs = [SECURITY_ATTRIBUTES_SIZE, 0, 1].pack('III')
return [0, 0] if createPipe.Call(read_handle, write_handle, sec_attrs,
0).zero?
[read_handle.unpack('I')[0], write_handle.unpack('I')[0]]
end
open_osfhandle = Win32API.new("msvcrt", "_open_osfhandle", ['L','L'],
'L')
fdopen = Win32API.new("msvcrt", "_fdopen", ['L','P'], 'L')
fgets = Win32API.new("msvcrt", "fgets", ['P', 'L', 'L'], 'L')
fputs = Win32API.new("msvcrt", "fputs", ['P', 'L'], 'L')
fclose = Win32API.new("msvcrt", "fclose", ['L'], 'L')
h_in, h_out = create_pipe
f_in = open_osfhandle.call(h_in, O_RDONLY | O_BINARY)
f_out = open_osfhandle.call(h_out, O_WRONLY | O_BINARY)
if true
# This code DOES work, so everything is fine up to this point
stream_in = fdopen.call(f_in, 'rb')
stream_out = fdopen.call(f_out, 'wb')
fputs.call("Hellooooo\000", stream_out)
fclose.call(stream_out)
buffer = "\000" * 200
fgets.call(buffer, 200, stream_in)
puts buffer[0..8]
else
# This does NOT work, why oh why?
IO.new(f_in, 'rb')
#=> No such file or directory (Errno::ENOENT)
IO.new(f_out, 'wb')
end
---------------------------------------------------------------