Subject:
Re: [ruby-ffi] Passing a struct by value, and typedef
From:
postmodern
Date:
3/3/13 7:45 PM
To:
ruby-ffi@googlegroups.com

You want :pointer in this case. I believe :buffer_out is a meant as a hint to FFI that data will be written back into an Array of chars/ints.

On 03/03/2013 05:41 PM, Maurizio De Santis wrote:
Another question: glibtop_get_cpu takes a struct as parameter, and fills it with informations about cpu.

I declared it as

attach_function :glibtop_get_cpu, [:pointer], :void

I think I can substitute :pointer with :buffer_out , am I right?

--

Maurizio De Santis


2013/3/4 Maurizio De Santis <desantis.maurizio@gmail.com>
Thank you a lot, your suggestions are precious.

--

Maurizio De Santis


2013/3/3 postmodern <postmodern.mod3@gmail.com>
You can simplify that code to just:
a = LibGtop::GlibtopCpu.new
LibGtop.glibtop_get_cpu(a)
p a[:frequency]
This will allocate memory for a GlibtopCpu struct, pass the pointer to the memory to glibtop_get_cpu and access to the struct field within the memory. Once you are done with the "a" variable, Ruby will just GC it and FFI will free the underlying memory.


On 03/02/2013 07:54 PM, Maurizio De Santis wrote:
Thank you. Now, the code runs without errors:

require 'ffi'

module LibGtop
 
  extend FFI::Library
  ffi_lib 'libgtop-2.0'

  typedef :uint64, :guint64

  attach_function :glibtop_get_cpu, [:pointer], :void

  class GlibtopCpu < FFI::Struct
    layout :flags,         :guint64,
           :total,         :guint64,
           :user,          :guint64,
           :nice,          :guint64,
           :sys,           :guint64,
           :idle,          :guint64,
           :iowait,        :guint64,
           :irq,           :guint64,
           :softirq,       :guint64,
           :frequency,     :guint64,
           :xcpu_total,   [:guint64, 32],
           :xcpu_user,    [:guint64, 32],
           :xcpu_nice,    [:guint64, 32],
           :xcpu_sys,     [:guint64, 32],
           :xcpu_idle,    [:guint64, 32],
           :xcpu_iowait,  [:guint64, 32],
           :xcpu_irq,     [:guint64, 32],
           :xcpu_softirq, [:guint64, 32],
           :xcpu_flags,    :guint64
  end

end


# taken from https://github.com/ffi/ffi/wiki/Structs
pointer = FFI::MemoryPointer.new :uint64, LibGtop::GlibtopCpu.size, true
a = LibGtop::GlibtopCpu.new pointer
LibGtop.glibtop_get_cpu(a)
p a[:frequency]


Another question: I initialized the pointer with clear = true, because the struct pointed by the pointer gets filled by glibtop_get_cpu, and then must be managed by Ruby, since glibtop_get_cpu just fills the struct. Am I wrong?

--

Maurizio De Santis


2013/3/3 postmodern <postmodern.mod3@gmail.com>
You need to find out guint64's underlying type, and create the typedef in Ruby:

module LibGtop
  extend FFI::Library

  typedef :uint64, :guint64
end

On 03/02/2013 06:06 PM, Maurizio De Santis wrote:
I am writing a libgtop2 wrapper using ffi in order to learn how to use ffi; I am new to ffi, so I have a lot of doubts.

libgtop2 lets get system and processes informations (cpu usage, memory usage, ...).

Here some informations about glibtop_get_cpu:

Library function `glibtop_get_cpu':

     void glibtop_get_cpu (glibtop_cpu *buf);
     void glibtop_get_cpu_l (glibtop *server, glibtop_cpu *buf);

   Declaration of `glibtop_cpu' in `<glibtop/cpu.h>':

     typedef struct _glibtop_cpu     glibtop_cpu;

     struct _glibtop_cpu
     {
         guint64   flags,
             total,
             user,
             nice,
             sys,
             idle,
             iowait,
             irq,
             softirq,
             frequency,
             xcpu_total [GLIBTOP_NCPU],
             xcpu_user [GLIBTOP_NCPU],
             xcpu_nice [GLIBTOP_NCPU],
             xcpu_sys  [GLIBTOP_NCPU],
             xcpu_idle [GLIBTOP_NCPU],
             xcpu_iowait [GLIBTOP_NCPU],
             xcpu_irq [GLIBTOP_NCPU],
             xcpu_softirq [GLIBTOP_NCPU],
             xcpu_flags;
     };

...



Here is what I wrote:

require 'ffi'

class GlibtopCpu < FFI::Struct
  layout :flags,        :guint64,
         :total,        :guint64,
         :user,         :guint64,
         :nice,         :guint64,
         :sys,          :guint64,
         :idle,         :guint64,
         :iowait,       :guint64,
         :irq,          :guint64,
         :softirq,      :guint64,
         :frequency,    :guint64,
         :xcpu_total,   :guint64,
         :xcpu_user,    :guint64,
         :xcpu_nice,    :guint64,
         :xcpu_sys,     :guint64,
         :xcpu_idle,    :guint64,
         :xcpu_iowait,  :guint64,
         :xcpu_irq,     :guint64,
         :xcpu_softirq, :guint64,
         :xcpu_flags,   :guint64
end

module LibGtop
 
  extend FFI::Library
  ffi_lib 'libgtop-2.0'
  attach_function :glibtop_get_cpu, [:pointer], :void

end

# taken from https://github.com/ffi/ffi/wiki/Structs
pointer = FFI::MemoryPointer.new :byte, GlibtopCpu.size, false
a = GlibtopCpu.new pointer
p LibGtop.glibtop_get_cpu(a)


Executing this gives (unsurprisingly) an error:

$ ruby lib/lib_gtop.rb
/home/izietto/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/ffi-1.4.0/lib/ffi/types.rb:57:in `find_type': unable to resolve type 'guint64' (TypeError)
    from /home/izietto/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/ffi-1.4.0/lib/ffi/struct.rb:316:in `find_type'
    from /home/izietto/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/ffi-1.4.0/lib/ffi/struct.rb:309:in `find_field_type'
    from /home/izietto/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/ffi-1.4.0/lib/ffi/struct.rb:351:in `array_layout'
    from /home/izietto/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/ffi-1.4.0/lib/ffi/struct.rb:261:in `layout'
    from lib/lib_gtop.rb:4:in `<class:GlibtopCpu>'
    from lib/lib_gtop.rb:3:in `<main>'


It doesn't find the guint64 type; how should I declare it?

Also: xcpu_total, xcpu_user are arrays... how should I declare them?

Finally... if someone could give me an explanation and an example of how to implement the bind to glibtop_get_cpu, I would appreciate it very much :)
--
 
---
You received this message because you are subscribed to the Google Groups "ruby-ffi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-ffi+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 


-- 
Blog: http://postmodern.github.com/
GitHub: https://github.com/postmodern
Twitter: @postmodern_mod3
PGP: 0xB9515E77

--
 
---
You received this message because you are subscribed to the Google Groups "ruby-ffi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-ffi+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 


-- 
Blog: http://postmodern.github.com/
GitHub: https://github.com/postmodern
Twitter: @postmodern_mod3
PGP: 0xB9515E77


--
 
---
You received this message because you are subscribed to the Google Groups "ruby-ffi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-ffi+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 


-- 
Blog: http://postmodern.github.com/
GitHub: https://github.com/postmodern
Twitter: @postmodern_mod3
PGP: 0xB9515E77