# Learning extending ruby

**URL:** <https://rubytalk.org/t/learning-extending-ruby/11272>\
**Category:** ruby-talk\
**Created:** [28 April 2004 07:04 UTC](https://rubytalk.org/t/learning-extending-ruby/11272 "2004-04-28T07:04:02Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dominik\_Werder2](https://avatars.discourse-cdn.com/v4/letter/d/fbc32d/32.png) [@Dominik\_Werder2](https://rubytalk.org/u/Dominik_Werder2)\
**Post date:** [28 April 2004 07:04 UTC](https://rubytalk.org/t/learning-extending-ruby/11272/1 "2004-04-28T07:04:02Z")

</div>

Hello!

Could somebody help me with this small piece of code?  
I’m learning how to extend ruby with C code.  
What I want to do here is creating a class in C and use it in ruby.  
The class should have a instance variable named myvar. This works so far.  
But now how do I create the accessor methods for this variable?

Thank you!  
Dominik

Here is the init method in C:

static VALUE t\_init(VALUE self)  
{  
VALUE str = rb\_str\_new2(“default string”);  
rb\_iv\_set(self, “@myvar”, str);  
rb\_define\_attr(str, “myvar”, 1, 1);  
return self;  
}

BTW: Is there any good doc beside the prag. prog. guide about extending ruby?

---

<div class="post-metadata">

**Author:** ![Laurent\_Julliard4](https://avatars.discourse-cdn.com/v4/letter/l/ebca7d/32.png) [@Laurent\_Julliard4](https://rubytalk.org/u/Laurent_Julliard4)\
**Post date:** [28 April 2004 07:49 UTC](https://rubytalk.org/t/learning-extending-ruby/11272/2 "2004-04-28T07:49:03Z")

</div>

> Hello!
> 
> Could somebody help me with this small piece of code?  
> I’m learning how to extend ruby with C code.  
> What I want to do here is creating a class in C and use it in ruby.

you want this?  
VALUE rb\_define\_class(const char \*name, VALUE super)

> BTW: Is there any good doc beside the prag. prog. guide about extending ruby?

README.EXT may help  
[http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/README.EXT?rev=1.18](http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/README.EXT?rev=1.18)

> **···**
>
> il 28 Apr 2004 00:02:46 -0700, [dwerder@gmx.net](mailto:dwerder@gmx.net) (Dominik Werder) ha scritto::

---

<div class="post-metadata">

**Author:** ![Dick\_Davies1](https://avatars.discourse-cdn.com/v4/letter/d/22d042/32.png) [@Dick\_Davies1](https://rubytalk.org/u/Dick_Davies1)\
**Post date:** [28 April 2004 10:13 UTC](https://rubytalk.org/t/learning-extending-ruby/11272/3 "2004-04-28T10:13:21Z")

</div>

- Dominik Werder [dwerder@gmx.net](mailto:dwerder@gmx.net) [0404 08:04]:

> static VALUE t\_init(VALUE self)  
> {  
> VALUE str = rb\_str\_new2(“default string”);  
> rb\_iv\_set(self, “@myvar”, str);  
> rb\_define\_attr(str, “myvar”, 1, 1);  
> return self;  
> }
> 
> BTW: Is there any good doc beside the prag. prog. guide about extending ruby?

Have a look at:

> **[WebMD - Better information. Better health.](https://www.webmd.com/?RubyApi)**
>
> The leading source for trustworthy and timely health and medical news and information. Providing credible health information, supportive community, and educational services by blending award-winning expertise in content, community services, expert...

> **···**
>
> –  
> Lewis’s Law of Travel:  
> The first piece of luggage out of the chute doesn’t belong to  
> anyone, ever.  
> Rasputin :: Jack of All Trades - Master of Nuns

---

<div class="post-metadata">

**Author:** ![Elbows](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@Elbows](https://rubytalk.org/u/Elbows)\
**Post date:** [30 April 2004 12:39 UTC](https://rubytalk.org/t/learning-extending-ruby/11272/4 "2004-04-30T12:39:01Z")

</div>

I don’t mean to discourage you from learning, but you might want to  
look into using SWIG ([www.swig.org](http://www.swig.org)) instead of writing extensions by  
hand. I can say from personal experience that it will save you lots of  
headaches.

Nathan

[dwerder@gmx.net](mailto:dwerder@gmx.net) (Dominik Werder) wrote in message news:[31033452.0404272302.53dfa004@posting.google.com](mailto:31033452.0404272302.53dfa004@posting.google.com)…

> **···**
>
> > Hello!
> > 
> > Could somebody help me with this small piece of code?  
> > I’m learning how to extend ruby with C code.  
> > What I want to do here is creating a class in C and use it in ruby.  
> > The class should have a instance variable named myvar. This works so far.  
> > But now how do I create the accessor methods for this variable?
> > 
> > Thank you!  
> > Dominik
> > 
> > Here is the init method in C:
> > 
> > static VALUE t\_init(VALUE self)  
> > {  
> > VALUE str = rb\_str\_new2(“default string”);  
> > rb\_iv\_set(self, “@myvar”, str);  
> > rb\_define\_attr(str, “myvar”, 1, 1);  
> > return self;  
> > }
> > 
> > BTW: Is there any good doc beside the prag. prog. guide about extending ruby?

---

<div class="post-metadata">

**Author:** ![Dominik\_Werder2](https://avatars.discourse-cdn.com/v4/letter/d/fbc32d/32.png) [@Dominik\_Werder2](https://rubytalk.org/u/Dominik_Werder2)\
**Post date:** [28 April 2004 15:49 UTC](https://rubytalk.org/t/learning-extending-ruby/11272/5 "2004-04-28T15:49:02Z")

</div>

Sorry, my description wasnt good enough…

At the bottom of the message is the complete C source code.  
The problem is where I put the big comment. At that line, I try to  
create attribute accessor methods so that I can easily read and write  
this variable (“myvar”) from ruby land…

I thought rb\_define\_attr() works like:  
class Test  
attr\_reader :myvar  
end  
doesn’t it?

#include “/usr/local/lib/ruby/1.8/i686-linux/ruby.h”

VALUE cRubyTest;

static VALUE t\_init(VALUE self)  
{  
VALUE str=rb\_str\_new2(“default string”);  
rb\_define\_attr(str, “myvar”, 1, 1); # \<------- PROBLEM!  
rb\_iv\_set(self, “@myvar”, str);  
return self;  
}

static VALUE t\_add(VALUE self, VALUE anObject)  
{  
VALUE arr;  
arr = rb\_iv\_get(self, “@arr”);  
rb\_ary\_push(arr, anObject);  
rb\_eval\_string(“puts “testing…””);  
return arr;  
}

static VALUE t\_change(VALUE self) {  
rb\_iv\_set(self, “@myvar”, rb\_str\_new2(“new string”));  
return self;  
}

void Init\_cRubyTest() {  
cRubyTest = rb\_define\_class(“Test”, rb\_cObject);  
rb\_define\_method(cRubyTest, “initialize”, t\_init, 0);  
rb\_define\_method(cRubyTest, “add”, t\_add, 1);  
rb\_define\_method(cRubyTest, “change”, t\_change, 0);  
}

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [30 April 2004 23:19 UTC](https://rubytalk.org/t/learning-extending-ruby/11272/6 "2004-04-30T23:19:03Z")

</div>

Nathan Weston wrote:

> I don’t mean to discourage you from learning, but you might want to  
> look into using SWIG ([www.swig.org](http://www.swig.org)) instead of writing extensions by  
> hand. I can say from personal experience that it will save you lots of  
> headaches.
> 
> Nathan
> 
> [dwerder@gmx.net](mailto:dwerder@gmx.net) (Dominik Werder) wrote in message  
> news:[31033452.0404272302.53dfa004@posting.google.com](mailto:31033452.0404272302.53dfa004@posting.google.com)…
> 
> > Hello!
> > 
> > Could somebody help me with this small piece of code?  
> > I’m learning how to extend ruby with C code.  
> > What I want to do here is creating a class in C and use it in ruby.  
> > The class should have a instance variable named myvar. This works so far.  
> > But now how do I create the accessor methods for this variable?
> > 
> > Thank you!  
> > Dominik
> > 
> > Here is the init method in C:
> > 
> > static VALUE t\_init(VALUE self)  
> > {  
> > VALUE str = rb\_str\_new2(“default string”);  
> > rb\_iv\_set(self, “@myvar”, str);  
> > rb\_define\_attr(str, “myvar”, 1, 1);  
> > return self;  
> > }

It’s definitely worth learning the ruby API itself, first. This is from  
the Pickaxe chapter on extending ruby:

> **···**
>
> * * *
> 
> void rb\_define\_attr(VALUE variable, const char \*name, int read, int write)
> 
> ## Creates accessor methods for the given variable, with the given name. If read is nonzero, create a read method; if write is nonzero, create a write method.
> 
> This is apparently a typo, since class.c has:
> 
> rb\_define\_attr(klass, name, read, write)  
> VALUE klass;  
> const char \*name;  
> int read, write;
> 
> So the first argument should be the class you are defining the attr in.  
> This should be called in your Init\_module method
> 
> If you want to access data faster from C, you may want to define your  
> own DATA class and store your variable in the C data structure part of  
> the object, rather than in ruby ivars. (See README.EXT in the ruby  
> distribution for details.) That saves you the time it takes to do lookup  
> in the ivar table. OTOH, if you go this way you have to make sure the  
> garbage collector knows about any ruby objects stored in the data  
> struct–you have to define mark() and free() functions.
> 
> SWIG can help automate the process of wrapping classes and defining  
> accessors, which is especially nice if you have a huge library to wrap.
> 
> If you are starting from scratch to develop an extension, you might want  
> to look at my cgenerator library, which takes a different, more dynamic,  
> approach than SWIG:
> 
> [http://raa.ruby-lang.org/list.rhtml?name=cgenerator](http://raa.ruby-lang.org/list.rhtml?name=cgenerator)
> 
> Using cgen, you can “include CShadow” in one of your classes, and define  
> attributes that are stored in a C data structure rather than as ivars.  
> The memory management stuff is handled automatically. Inheritance is  
> also handled transparently. Just call #commit on your class, and it  
> compiles and loads the library.
> 
> Here’s an example based on the code you wrote:
> 
> require ‘cgen/cshadow’
> 
> class MyClass  
> include CShadow  
> shadow\_attr\_accessor :my\_c\_string =\> “char \*my\_string”  
> shadow\_attr\_accessor :my\_ruby\_string =\> String  
> shadow\_attr\_accessor :my\_ruby\_object =\> Object
> 
> ```
> def initialize
> # Must use 'self.varname = value', or else ruby will assign to
> # local var
> self.my_c_string = "default string"
> # stored as null-terminated char *
> 
> self.my_ruby_string = "default string"
> # stored as ruby VALUE string, after checking type is String
> 
> self.my_ruby_object = "default string"
> # stored as ruby VALUE string, no type checking
> end
> 
> def inspect
> "<#{self.class}: %p, %p, %p>" %
> [my_c_string, my_ruby_string, my_ruby_object]
> end
> 
> # easy way to add a method written in C
> define_c_method :foo do
> 
> c_array_args { # interface to rb_scan_args
> required :x
> optional :y
> rest :stuff
> block :block
> typecheck :x => Numeric
> default :y => "INT2NUM(NUM2INT(x) + 1)"
> }
> 
> declare :result => "VALUE result"
> 
> body %{
> result = rb_funcall(block, #{declare_symbol :call}, 4,
> shadow->my_ruby_string,
> x, y, stuff);
> }
> # note use of shadow var to access shadow attrs
> 
> returns "result"
> end
> 
> ```
> 
> end
> 
> MyClass.commit # write C lib, compile, load
> 
> my\_obj = MyClass.new  
> p my\_obj
> 
> # ==\> \<MyClass: “default string”, “default string”, “default string”\>
> 
> block = proc do |str, x, y, stuff|  
> “%s, %p, %p, %p” % [str, x, y, stuff]  
> end
> 
> p my\_obj.foo(1, &block)
> 
> # ==\> “default string, 1, 2, ”
> 
> p my\_obj.foo(5, 0, “stuff”, “more stuff”, &block)
> 
> # ==\> “default string, 5, 0, ["stuff", "more stuff"]”

---

<div class="post-metadata">

**Author:** ![ts1](https://avatars.discourse-cdn.com/v4/letter/t/a8b319/32.png) [@ts1](https://rubytalk.org/u/ts1)\
**Post date:** [28 April 2004 16:13 UTC](https://rubytalk.org/t/learning-extending-ruby/11272/7 "2004-04-28T16:13:43Z")

</div>

> class Test  
> &nbsp;&nbsp;attr\_reader :myvar  
> end

When you write this, you call the class Method ::attr\_reader. This mean  
that in your case, you must call rb\_define\_attr() with cRubyTest

> void Init\_cRubyTest() {  
> &nbsp;&nbsp;cRubyTest = rb\_define\_class("Test", rb\_cObject);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rb\_define\_attr(cRubyTest, "myvar", Qtrue, Qfalse);

> &nbsp;&nbsp;rb\_define\_method(cRubyTest, "initialize", t\_init, 0);  
> &nbsp;&nbsp;rb\_define\_method(cRubyTest, "add", t\_add, 1);  
> &nbsp;&nbsp;rb\_define\_method(cRubyTest, "change", t\_change, 0);  
> }

Guy Decoux

---

<div class="post-metadata">

**Author:** ![Kristof\_Bastiaensen1](https://avatars.discourse-cdn.com/v4/letter/k/9fc29f/32.png) [@Kristof\_Bastiaensen1](https://rubytalk.org/u/Kristof_Bastiaensen1)\
**Post date:** [28 April 2004 16:19 UTC](https://rubytalk.org/t/learning-extending-ruby/11272/8 "2004-04-28T16:19:01Z")

</div>

Hi,

> **···**
>
> On Wed, 28 Apr 2004 08:44:18 -0700, Dominik Werder wrote:
> 
> > rb\_define\_attr(str, “myvar”, 1, 1); # \<------- PROBLEM!
> 
> The attr methods work on the class, not on the instance.  
> So try this instead (from Init\_cRubyTest):
> 
> rb\_define\_attr(cRubyTest, “myvar”, 1, 1);
> 
> Kristof

---

<div class="post-metadata">

**Author:** ![Dominik\_Werder2](https://avatars.discourse-cdn.com/v4/letter/d/fbc32d/32.png) [@Dominik\_Werder2](https://rubytalk.org/u/Dominik_Werder2)\
**Post date:** [28 April 2004 22:04 UTC](https://rubytalk.org/t/learning-extending-ruby/11272/9 "2004-04-28T22:04:01Z")

</div>

Works like a wonder, thank you very much!

> **···**
>
> > > void Init\_cRubyTest() {  
> > > cRubyTest = rb\_define\_class(“Test”, rb\_cObject);
> > 
> > ```
> > rb_define_attr(cRubyTest, "myvar", Qtrue, Qfalse);
> > 
> > ```
> > 
> > > rb\_define\_method(cRubyTest, “initialize”, t\_init, 0);  
> > > rb\_define\_method(cRubyTest, “add”, t\_add, 1);  
> > > rb\_define\_method(cRubyTest, “change”, t\_change, 0);  
> > > }
