[Win32utils-devel] Using callbacks with ReadFileEx

Berger, Daniel Daniel.Berger at qwest.com
Tue Sep 25 09:29:48 EDT 2007


Hi all,

First, I just realized I'll need to go back and fix some of the
prototype declarations for windows-pr. The callback parameters will now
need to be set to 'K'. ReadFileEx is one example of this. For purposes
of my question, let's assume ReadFileEx has been declared like so:

API.new('ReadFileEx', 'LPLPK', 'B')

Now that we have callback support in win32-api, I thought I'd give
asynchronous IO a shot. Problem is, I'm not sure how to do it in this
case. What I would like is for the user to be able to provide a block,
and have that block called once the read is finished. Here's what I've
tried so far:

require 'windows/file'
require 'windows/handle'
require 'windows/error'
require 'windows/synchronize'
require 'win32/event'

module Windows
   module NIO
      include Windows::File
      include Windows::Handle
      include Windows::Error
      include Windows::Synchronize
      extend Windows::File
      extend Windows::Handle
      extend Windows::Error
      extend Windows::Synchronize

      class Error < StandardError; end

      def self.read_async(file, length=nil, offset=0, &block)
         handle = CreateFile(
            file,
            FILE_READ_DATA,
            FILE_SHARE_READ,
            0,
            OPEN_EXISTING,
            FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
            0
         )

         if handle == INVALID_HANDLE_VALUE
            raise Error, get_last_error
         end

         func = Win32::API::Callback.new('LLP', 'V'){
            block.call
         }
         
         overlapped = 0.chr * 20

         if offset > 0
            overlapped[8,4] = [offset].pack('L') # OVERLAPPED.Offset
         end
         
         # Ruby's File.size fails for files over 2gb
         unless length
            size = [0].pack('Q')
            GetFileSizeEx(handle, size)
            length = size.unpack('Q').first
         end

         buf = 0.chr * length
         
         bool = ReadFileEx(
            handle,
            buf,
            length,
            overlapped,
            func
         )

         unless bool
            err = get_last_error()
            CloseHandle(handle)
            raise Error, err
         end
         
         CloseHandle(handle)
         
         buf[0,length]
      end
   end
end

if $0 == __FILE__
   include Win32

   file = 'test.txt'
   data = NIO.read_async(file){ puts "Hello" }
   p data
end

When I run this, however, I get this error:

C:/ruby/lib/ruby/site_ruby/1.8/windows/error.rb:329:in `call': wrong
number of parameters: expected 1, got 0 (ArgumentEr
ror)
        from C:/ruby/lib/ruby/site_ruby/1.8/windows/error.rb:329:in
`get_last_error'
        from nio.rb:124:in `read_async'
        from nio.rb:140

What am I doing wrong here?

Thanks,

Dan


This communication is the property of Qwest and may contain confidential or
privileged information. Unauthorized use of this communication is strictly 
prohibited and may be unlawful.  If you have received this communication 
in error, please immediately notify the sender by reply e-mail and destroy 
all copies of the communication and any attachments.


More information about the win32utils-devel mailing list