From: Joel VanderWerf Date: 2006-06-06T04:27:36+09:00 Subject: Re: Inheritance from c Phil Jackson wrote: > Hi All, > > I'm messing about with inheritance from my C application but can't get it to > work properly. Here is a quick overview of what I want to achieve: > > class Hello should parent Helloworld. Both use Data_Wrap_Struct to wrap up > and struct whos memory is allocated with ALLOC. Silly example: > > struct Hello_struct { > VALUE name; > } > > struct Helloworld_struct { > VALUE count; > } > > The trouble is when I try to call a function from a Helloworld instance that > reads/writes to a copy of the Hello_struct I get a segfault. This implies to > me that memory is not being allocated for Hello_struct. Do I have to tell > Heloworld that space for Hello needs to be allocated? If so how? I'm not sure I understand, but it sounds like you want your Helloworld instances to have both a Hello_struct and a Helloworld_struct as their data? And you want instance methods of the Hello class, when called on a Helloworld object, to operate on an inherited Hello_struct? This won't work, unfortunately. Ruby T_DATA objects have only one data pointer. They don't inherit data pointers from superclasses. You need to manage the inheritance of C structs somehow, possibly by embedding the Hello_struct members (or embed the struct itself) inside of Helloworld_struct: struct Helloworld_struct { VALUE name; VALUE count; } If you do this, then Hello methods defined in C just have to cast the data pointer to a Hello_struct *, and can then access the "name" member. I wrote the cgen/cshadow library (on RAA) to generate C code in this way, based on pure-ruby attribute declarations and "in-line" C code. This is the examples/inherit-example.rb, which I think is included in the download: ===== require 'cgen/cshadow' class Parent include CShadow shadow_attr_accessor :ruby_str => String shadow_attr_accessor :c_int => "int c_int" end class Child < Parent shadow_attr_accessor :obj => Object # VALUE type end Parent.commit # we're done adding attrs and methods, so make. x = Child.new x.ruby_str = "foo" x.obj = [1,2,3] x.c_int = 3 p x # ==> # ===== The generated code for the Child class ends up looking like this: typedef struct Child_Shadow { /* Parent_Shadow members */ VALUE self; VALUE ruby_str; // String; int c_int; VALUE obj; // Object; } Child_Shadow; ===== (The "self" member can be very useful--you can get back to the ruby object from the shadow struct.) See the other examples for samples of method definitions using in-line C code. A very brief snippet from complex.rb: ===== class MyComplex < Numeric include CShadow shadow_attr_accessor :re => "double re", :im => "double im" define_c_method(:abs) do include "" returns "rb_float_new(sqrt(pow(shadow->re, 2) + pow(shadow->im, 2)))" end end ===== -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407