Writing a new method in C for a subclass

Given the available documentation and having gone through the ruby
source code, I understand how to write a new method in C.

My question is, how do I write a “new” method for a class that extends
another class. Specifically, I want to extend Array, but I am not
clear on exactly how to do this. If my conception is correct, then
appears to me that I must make a struct with all of the values used by
my class. However, since I am extending Array, I am not sure whether I
need to some how construct it so that it is uses the RBasic, len, capa,
and ptr values in the Array class and then adds its own values, or if I
can simply duplicate these in my extension struct. Unless all
inheritance is handled by rb_define_class, something like this would
seem to be needed in order to preserve the existing functionality that
I want to inherit from Array.

Right now, I define an ‘initialize’ method in C, instantiate the object
(which extends Array) in Ruby, pass the already instantiated object as
a parameter to another C method that returns that same object populated
with the appropriate data, and push that object onto an array. This
process is enclosed in a loop that can conceivably repeat hundreds of
thousands of times, so speed is of the essence. It strikes me that it
would be faster to instantiate the object in the C method that
currently takes it as a parameter, and simply return that object–or
better yet execute whole loop in the C method so that it returns the
array with all of the objects already pushed onto it. Does this sound
sensible?

At any rate, I may have overlooked something, but I haven’t found any
documentation on this, and I’d have to dig much deeper into the source
code to figure it out. Could someone please clarify this?

Thanks,

Dave

···

David King Landrith
(w) 617.227.4469x213
(h) 617.696.7133

One useless man is a disgrace, two
are called a law firm, and three or more
become a congress – John Adams

public key available upon request

Yes you should be able to subclass Array directly. Try:

rb_cMyArray = rb_define_class("MyArray", rb_cArray);

which I understand to be the same as

MyArray = Class.new(Array)

or

class MyArray < Array
end

Regards,

Brian.

···

On Tue, Mar 25, 2003 at 01:07:40AM +0900, David Landrith wrote:

Unless all inheritance is handled by rb_define_class

can simply duplicate these in my extension struct. Unless all
inheritance is handled by rb_define_class, something like this would
seem to be needed in order to preserve the existing functionality that
I want to inherit from Array.

Well, I've not understood what you want to do, but try this

pigeon% cat aa.c
#include "ruby.h"

static VALUE
aa_aa(obj)
    VALUE obj;
{
    int i, j;
    for (i = 0; i < RARRAY(obj)->len; i++) {
        j = NUM2INT(RARRAY(obj)->ptr[i]);
        RARRAY(obj)->ptr[i] = INT2NUM(j + 1);
    }
}

void Init_aa()
{
    VALUE aa_cAa;

    aa_cAa = rb_define_class("Aa", rb_cArray);
    rb_define_method(aa_cAa, "aa", aa_aa, 0);
}
pigeon%

pigeon% ruby -raa -e 'a = Aa.new; a << 1; a << 2; a.aa; p a'
[2, 3]
pigeon%

Guy Decoux

This much I understand. This is a complicated topic, and it looks
like what I wrote before was rather convoluted. If anyone is able to
restate what I’m trying to ask in a more straightforward manner, I’d
appreciate it.

I am wondering if there is anything special that I must do to create a
method that instantiates a new MyArray object in c. All of the
examples of “new” methods (meaning a methods that are declared using
the form rb_define_singleton_method(myClass, “new”, myClass_new, argc)
simply extend rb_cObj.

I know that if I extend the Array, then I will create a class whose
objects will have the same set of values as Array. It seems that in
order to define a class from the ground up (meaning including the “new”
method), you need to create a struct, wrap it, and return the VALUE
pointing to the wrap. I can do this easily enough, but if I am
extending a class, do I create a struct that points to the super class?
or do I create a struct that contains all of the values in the
superclass? or am I on entirely the wrong track?

···

On Monday, March 24, 2003, at 11:30 AM, Brian Candler wrote:

On Tue, Mar 25, 2003 at 01:07:40AM +0900, David Landrith wrote:

Unless all inheritance is handled by rb_define_class

Yes you should be able to subclass Array directly. Try:

rb_cMyArray = rb_define_class("MyArray", rb_cArray);

which I understand to be the same as

MyArray = Class.new(Array)

or
class MyArray < Array
end


David King Landrith
(w) 617.227.4469x213
(h) 617.696.7133

One useless man is a disgrace, two
are called a law firm, and three or more
become a congress – John Adams

public key available upon request

If you’re trying to do something very deep, which involves fudging with the
implementation of Array itself, rather than just adding methods to Array,
then I’m out of my depth :slight_smile:

It does seem to me that whatever you write is going to be heavily tied to
the particular implementation of Array which exists now, and therefore may
not be very portable. Without knowing what you’re trying to achieve, would
be it be worth using ‘has_a’ instead of ‘is_a’? That is, create a new object
which in turn contains an instance of an Array? You can then mechanically
delegate to it.

Regards,

Brian.

···

On Tue, Mar 25, 2003 at 05:21:05AM +0900, David King Landrith wrote:

This much I understand. This is a complicated topic, and it looks
like what I wrote before was rather convoluted. If anyone is able to
restate what I’m trying to ask in a more straightforward manner, I’d
appreciate it.

I am wondering if there is anything special that I must do to create a
method that instantiates a new MyArray object in c. All of the
examples of “new” methods (meaning a methods that are declared using
the form rb_define_singleton_method(myClass, “new”, myClass_new, argc)
simply extend rb_cObj.

Hi,

I am wondering if there is anything special that I must do to create a
method that instantiates a new MyArray object in c. All of the
examples of “new” methods (meaning a methods that are declared using
the form rb_define_singleton_method(myClass, “new”, myClass_new, argc)
simply extend rb_cObj.

If you’re using 1.8.0, you just need to call

ary = rb_obj_alloc(YourArraySubclass);

to get new instance of your class. But since allocated instance is an
empty array, you need to call rb_ary_store() to store object to
allocate internal buffer.

Making a subclass of built-in classes is more difficult than making
subclass of Object. You may need to dig into the interpreter
source code.

						matz.
···

In message “Re: Writing a new method in C for a subclass” on 03/03/25, David King Landrith dave@landrith.com writes:

If you’re trying to do something very deep, which involves fudging
with the
implementation of Array itself, rather than just adding methods to
Array,
then I’m out of my depth :slight_smile:

It does seem to me that whatever you write is going to be heavily tied
to
the particular implementation of Array which exists now, and therefore
may
not be very portable. Without knowing what you’re trying to achieve,
would
be it be worth using ‘has_a’ instead of ‘is_a’? That is, create a new
object
which in turn contains an instance of an Array? You can then
mechanically
delegate to it.

I’m not sure that what I am trying to do is very complicated, and I
certainly don’t want to tie it to any specific implementation of Array.

I know that I’m not doing a great job of explaining this, but I have
not sensed that there is a specific lingo that I am supposed to be
using to describe how the C extension API works with any real
granularity. If I am wrong about this, I’d like a few pointers on
where to look to become more familiar with it.

At any rate, let my try to explain again:

If I want to make a new Array in c, I can type rb_ary_new2(long int) –
or rb_ary_new() which calls it – in my c program/extension, and one
may look at implementation of these methods in array.c. So suppose I
want to create a class that extends Array then instantiate it in c. If
I do this, then I must have a function – say myArray_new() – in C
that wraps up a structure and returns a pointer to it much like
rb_ary_new2(long int). Are there any special requirements for
myArray_new to make sure that it’s values are accessible by the methods
of its superclass? Do I need to somehow include a pointer the the
rb_cArray object or the RArray struct in the struct used by myArray?
Or do I simply make a struct for myArray that is a superset of the
values in the RArray struct and let the “define_class” method handle
the details?

Does this make sense?

···

David King Landrith
(w) 617.227.4469x213
(h) 617.696.7133

One useless man is a disgrace, two
are called a law firm, and three or more
become a congress – John Adams

public key available upon request

Thanks for the clarification. This answers my question, and an empty
array subclass is precisely what I’m after.

Unfortunately, I am using 1.6.8. How stable is 1.8?

(By the way, I received this moments after I sent my previous email.)

···

On Monday, March 24, 2003, at 10:48 PM, Yukihiro Matsumoto wrote:

Hi,

In message “Re: Writing a new method in C for a subclass” > on 03/03/25, David King Landrith dave@landrith.com writes:

I am wondering if there is anything special that I must do to create a
method that instantiates a new MyArray object in c. All of the
examples of “new” methods (meaning a methods that are declared using
the form rb_define_singleton_method(myClass, “new”, myClass_new, argc)
simply extend rb_cObj.

If you’re using 1.8.0, you just need to call

ary = rb_obj_alloc(YourArraySubclass);

to get new instance of your class. But since allocated instance is an
empty array, you need to call rb_ary_store() to store object to
allocate internal buffer.

Making a subclass of built-in classes is more difficult than making
subclass of Object. You may need to dig into the interpreter
source code.

  					matz.

David King Landrith
(w) 617.227.4469x213
(h) 617.696.7133

One useless man is a disgrace, two
are called a law firm, and three or more
become a congress – John Adams

public key available upon request

Hi,

Unfortunately, I am using 1.6.8. How stable is 1.8?

Fairly stable for daily matters. I’m always using 1.8.0 for my
works. And you will see 1.8.0 final release on somewhere in April.

If you need to stil to 1.6.x, you need to copy the function below to
your extension.

static VALUE
ary_alloc(klass)
VALUE klass;
{
NEWOBJ(ary, struct RArray);
OBJSETUP(ary, klass, T_ARRAY);

ary->len = 0;
ary->ptr = 0;
ary->aux.capa = 0;

return (VALUE)ary;

}

then call ary_alloc(YourArraySubclass) to get an empty instance.

						matz.
···

In message “Re: Writing a new method in C for a subclass” on 03/03/25, David Landrith dlandrith@mac.com writes: