Subject: [ruby-ffi] Re: Correct type for binary buffer in a String? |
From: candlerb |
Date: 5/6/11 3:09 AM |
To: ruby-ffi |
OK, I was being stupid. The last arg to getsockopt is a *pointer* to the buflen. Here is a working version using FFI::Buffer: ------------------------------------- require 'ffi' module Foo extend FFI::Library ffi_lib FFI::Library::LIBC attach_function :getsockopt, [:int, :int, :int, :buffer_inout, :buffer_inout], :int end require 'socket' s = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0) buf = FFI::Buffer.new :int buflen = FFI::Buffer.new :socklen_t buflen.put_int(0, buf.total) puts Foo.getsockopt(s.fileno, Socket::IPPROTO_IP, Socket::IP_TTL, buf, buflen) p buf.get_int(0) ------------------------------------- Now, I also tried it using plain String instead of FFI::Buffer, and it works. However if Ruby is sharing the underlying string storage between multiple strings (copy-on-write) then aliasing happens: str = "xxxx" buf = str.dup buflen = [buf.bytesize].pack("I") puts Foo.getsockopt(s.fileno, Socket::IPPROTO_IP, Socket::IP_TTL, buf, buflen) p buf # "@\000\000\000" p str # "@\000\000\000" as well!! Is that intentional? Perhaps if the argument is :buffer_inout then FFI should call rb_str_modify on the string first? Regards, Brian.