From: Joel VanderWerf Date: 2002-02-18T06:12:45+09:00 Subject: Re: Accessing C structure members from Ruby 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