Laurent Julliard wrote:
> 
> I'm in the process of writing a Ruby Extension for a C library. This C
> library has a number of C structures which I'm going to use as a basis
> to create the corresponding Ruby Classes. So far so good.
> 
> However instead of just using the Data_Wrap_Struct  facility to
> encompass these structures I'd like to put in place a mechanism where
> each member of the original C structure has an equivalent instance
> variable in the corresponding Ruby Class. What is the best way to do this?
> 
> I see two complementary approach for the moment but may be you'll have
> other ideas/tips:
> 
> 1) I can put in place a copy mechanism in the C extension so that
> whenever a method is called it copies all the instance variables in the
> corresponding C structure members, call the C function, and copy the C
> struct members back to the Ruby instance variables when the C function
> returns.
> 
> 2) In addition I could also define Ruby accessors (Get/Set) which are
> small C function which write to/ read from the appropriate C strcture
> member. I saw the rb_define_attr fucntion but unfortunately it looks
> like there is no way to hook accessors to "virtual" instance variables
> that would be actually be stored in C structure member. Am I missing
> something here?

(2) seems much better.

In the latest version of CGenerator, there is a mix-in called CShadow
that lets you easily add this kind of accessor to Ruby classes.

Briefly, you can do this:

class A
  include CShadow
  shadow_attr_accessor :x => "int x",
                       :y => "double y",
                       :obj => Object,
                       :h => Hash
end

A.commit  # generates C code, makes the lib, and loads it

a = A.new

a.y = 3
a.y       # ==> 3.0
a.h       # ==> nil
a.h = {1=>2}
a.h = 5   # ==> TypeError

Now you can use CShadow's define_method and define_class_method to work
directly with the C struct that contains these members. See
examples/matrix.rb and examples/complex.rb.

Shadow attributes manage mark/free and type checking, and it is easy to
add new attribute classes (float for example).

You can keep some data in C members, and other data in Ruby attrs, as
you like. You can include other .c files in the library just by putting
them in the same dir as the .c files generated by CShadow/CGenerator,
and you can access the shadow structs by #include-ing the header
generated for the library's main file.

It's at:

http://www.ruby-lang.org/en/raa-list.rhtml?name=CGenerator
http://redshift.sourceforge.net/cgen/

I wasn't going to post this yet, because:

 -- I haven't tried it on windows, just linux.
     (should be possible, but will need to call nmake instead
     of make if you're using it with MSVC)

 -- I'm still getting the serialization working
     (Thanks again, David B.)

I'll probably have these things in the next version, in a week or two.

--
Joel VanderWerf                          California PATH, UC Berkeley
mailto:vjoel / path.berkeley.edu                     Ph. (510) 231-9446
http://www.path.berkeley.edu                       FAX (510) 231-9512