[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