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 |
I think I can substitute :pointer with :buffer_out , am I right?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
--
--
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:
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.a = LibGtop::GlibtopCpu.new LibGtop.glibtop_get_cpu(a) p a[:frequency]
On 03/02/2013 07:54 PM, Maurizio De Santis wrote:
Thank you. Now, the code runs without errors: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?
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]
--
--
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:
You received this message because you are subscribed to the Google Groups "ruby-ffi" group.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 :) --
---
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-ffi+unsubscribe@googlegroups.com.
-- 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