[Win32utils-devel] Trouble getting a callback to work with FFI

Heesob Park phasis at gmail.com
Tue Jul 3 00:43:14 UTC 2012


Hi,

2012/7/3 Daniel Berger <djberg96 at gmail.com>

> Hi,
>
> I'm getting a segfault when I try to pass a callback proc to
> ReadFileEx. The proc fires, then the interpreter segfaults.
>
> Any ideas? I tried a blocking callback, too, but that didn't help.
>
> require 'ffi'
>
> class Windows
>  extend FFI::Library
>  ffi_lib :kernel32
>
>  class Overlapped < FFI::Struct
>    layout(
>      :Internal, :ulong,
>      :InternalHigh, :ulong,
>      :Offset, :ulong,
>      :OffsetHigh, :ulong,
>      :hEvent, :ulong
>    )
>  end
>
>  callback :completion_proc, [:ulong, :ulong, Overlapped], :void
>
>  attach_function :CloseHandle, [:ulong], :bool
>  attach_function :CreateFileA, [:string, :ulong, :ulong, :pointer,
> :ulong, :ulong, :ulong], :ulong
>  attach_function :ReadFileEx, [:ulong, :buffer_out, :ulong,
> Overlapped, :completion_proc], :bool
>  attach_function :GetOverlappedResult, [:ulong, :pointer, :pointer,
> :bool], :bool
>  attach_function :SleepEx, [:ulong, :bool], :ulong
>
>  OPEN_EXISTING             = 3
>  GENERIC_READ              = 0x80000000
>  FILE_SHARE_READ           = 0x00000001
>  FILE_FLAG_OVERLAPPED      = 0x40000000
>  FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000
>  INVALID_HANDLE_VALUE      = 0xFFFFFFFF
>  ERROR_IO_PENDING          = 997
>
>  def self.read(file)
>    flags = FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN
>
>    begin
>      handle = CreateFileA(
>        file,
>        GENERIC_READ,
>        FILE_SHARE_READ,
>        nil,
>        OPEN_EXISTING,
>        flags,
>        0
>      )
>
>      if handle == INVALID_HANDLE_VALUE
>        raise SystemCallError, FFI.errno, "CreateFile"
>      end
>
>      buf   = 0.chr * File.size(file)
>      olap  = Overlapped.new
>
>      cproc = Proc.new do |error, bytes, overlapped|
>        puts "Error: #{error}"
>        puts "Bytes: #{bytes}"
>        p overlapped
>      end
>
>      ### FAIL: cproc fires, but then I get a segfault
>      bool  = ReadFileEx(handle, buf, buf.size, olap, cproc)
>      errno = FFI.errno
>
>      SleepEx(1, true)
>
>      unless bool
>        if errno == ERROR_IO_PENDING
>          bytes = FFI::MemoryPointer.new(:ulong)
>          unless GetOverlappedResult(handle, olap, bytes, true)
>            raise SystemCallError, FFI.errno, "GetOverlappedResult"
>          end
>        else
>          raise SystemCallError, errno, "ReadFileEx"
>        end
>      end
>
>      buf.delete(0.chr)
>    ensure
>      CloseHandle(handle) if handle
>    end
>  end
> end
>
> File.open('small.txt', 'w'){ |fh| fh.puts "Hello World" }
> p Windows.read('small.txt')
>
>
I guess this is due to the calling convention mismatch.

If you add ffi_convention line, it will work.

...
class Windows
 extend FFI::Library
 ffi_lib :kernel32
 ffi_convention :stdcall  # add this line
...


Regards,
Park Heesob
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/win32utils-devel/attachments/20120703/b27c89e9/attachment.html>


More information about the win32utils-devel mailing list