Inheritance from c


#1

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?

Confused,
Phil


#2

Phil J. wrote:

}

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

==> #<Child:0xb7ba96f4 ruby_str=“foo”, c_int=3, obj=[1, 2, 3]>

=====

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 “<math.h>”
returns “rb_float_new(sqrt(pow(shadow->re, 2) + pow(shadow->im,
2)))”
end
end

=====


#3

On Tue, Jun 06, 2006 at 04:27:36 +0900, Joel VanderWerf wrote:

Phil J. wrote:

[ …snip… ]

struct Helloworld_struct {
    VALUE name;
    VALUE count;
}

This solved the problem, thanks. I’d made the assumption that Ruby would
build and manage the parent for me by calling new on it.

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:

I had a quick go with this, an excellent tool, very powerful. I would
certainly consider using it for guideline code in the future!

Thanks for your help,
Phil