From: Daniel Berger Date: 2009-08-09T21:21:31+09:00 Subject: Re: FFI, getutxent question On Aug 9, 2:54 am, Andrea Fazzi wrote: > Daniel Berger wrote: > > Info.getstuff # Null Pointer object > > Your script runs smoothly on my system (Ubuntu Linux) returning a proper > NativePointer object. It seems that the issue is related to your > environment rather then FFI. Ah, yes. I was on OS X. I tried again on Linux. > > > However, the call to getutxent() returns a NULL pointer. I'm guessing I > > have to tell it what kind of pointer to return, but I wasn't sure how to > > do that. How do I do that? > > You don't. Once you get a proper pointer object you'll use it to > instantiate the Utmpx class: > >   Utmpx.new(getutxent) > > The Utmpx class will be a subclass of FFI::Struct that mirrors the > layout of the C counterpart. Moreover, as I can see from libc reference > manual[1], utmpx has nested structs within. The good news is that > Ruby-FFI has support for nested structs. The bad one is that you have to > define all the nested structs by hand: > >   class Pid < FFI::Struct >     layout ... >   end Looks like FFI has a :pid_t type. I tried this but I'm still having trouble. Part of the problem may be that I'm not sure how to declare char[] struct members. The docs indicate there's a :char_array type, but FFI doesn't seem to like it. require 'ffi' class Info extend FFI::Library BOOT_TIME = 2 attach_function :setutxent, [], :void attach_function :getutxent, [], :pointer attach_function :endutxent, [], :void class Timeval < FFI::Struct layout(:tv_sec, :long, :tv_usec, :long) end class Utmpx < FFI::Struct layout( :ut_user, :char, 32 :ut_id, :char, 4 :ut_line, :char, 32 :ut_pid, :pid_t, :ut_type, :short, :ut_tv, Timeval ) end def self.getstuff time = nil begin setutxent() while ent = Utmpx.new(getutxent()) if ent[:ut_type] == BOOT_TIME time = Time.new(ent[:ut_tv][:tv_sec], ent[:ut_tv] [:tv_usec]) break end end ensure endutxent() end time end end Info.getstuff ruby boot_time.rb boot_time.rb:33:in `[]': NULL Pointer access attempted (FFI::NullPointerError) from boot_time.rb:33:in `getstuff' from boot_time.rb:46 Where line 33 is the ent[:ut_type] reference. Any suggestions? Regards, Dan