Accessing Ruby class from C extention

I know it’s possible to write Ruby in C but is it possible to instantiate
a Ruby object (defined only in a Ruby class; no C) in a C extention and
then call methods on that object in C?

I know we can instantiate Strings (rb_str_new2(“some string”)), Arrays
(rb_ary_new), and Hashes for example in a C extention, but these classes
are all defined in C.

I’m thinking it’s probably not possible to do this, but maybe there’s a
trick to it that I don’t know about… Otherwise I’ll just have to rewrite
several Ruby classes in RubyC.

Phil

Maybe I’m not understanding, but can’t you just call `new’ on the class you
want to instantiate?

Chris

Maybe I’m not understanding, but can’t you just call `new’ on the class you
want to instantiate?

···

----- Original Message -----
From: “Chris Pine” nemo@hellotree.com


Sorry if that was too short as to be unhelpful. What I meant was that, if
you have the class object on the C side, you can just call `new’ on it with
one of these:

rb_funcall
rb_funcall2
rb_funcall3
rb_apply

You will need to get the id for `new’ first, with this:

new_id = rb_intern (“new”);

Most of this is on page 193 of the pickaxe.

Or, you could just do this (which is slower):

rb_eval_string (“YourRubyClass.new”);

Chris

In article 006b01c30a8e$5b24ad70$6401a8c0@MELONBALLER,

···

Chris Pine nemo@hellotree.com wrote:

Maybe I’m not understanding, but can’t you just call `new’ on the class you
want to instantiate?

I want to call ‘new’ on the class on the C side. The more I think about
it, the more I doubt this is possible.

Phil

In article 007c01c30a90$9e798bc0$6401a8c0@MELONBALLER,

From: “Chris Pine” nemo@hellotree.com

Maybe I’m not understanding, but can’t you just call `new’ on the class you
want to instantiate?

Sorry if that was too short as to be unhelpful. What I meant was that, if
you have the class object on the C side, you can just call `new’ on it with
one of these:

rb_funcall
rb_funcall2
rb_funcall3
rb_apply

You will need to get the id for `new’ first, with this:

new_id = rb_intern (“new”);

Most of this is on page 193 of the pickaxe.

Or, you could just do this (which is slower):

rb_eval_string (“YourRubyClass.new”);

Hmmmm… but how does the C side ‘know’ where my Ruby class is defined?
There doesn’t seem to be a ‘rb_require’. I guess I should just try it
out. I suppose if on the Ruby side I’ve got:

require ‘SomeClass’
require ‘MyCExtention’

That perhaps MyCExtention might then have access to SomeClass (?)

Phil

···

Chris Pine nemo@hellotree.com wrote:

----- Original Message -----

Why? There’s nothing particularly special about calling the ‘new’ method of
a class. It will return a VALUE which is the object it created for you.

Regards,

Brian.

···

On Fri, Apr 25, 2003 at 03:52:30AM +0900, Phil Tomson wrote:

In article 006b01c30a8e$5b24ad70$6401a8c0@MELONBALLER,
Chris Pine nemo@hellotree.com wrote:

Maybe I’m not understanding, but can’t you just call `new’ on the class you
want to instantiate?

I want to call ‘new’ on the class on the C side. The more I think about
it, the more I doubt this is possible.

Its possible, I do it myself all the time.

char *name_of_class = "test";
VALUE klass = rb_const_get(rb_cObject, rb_intern(name_of_class));

// (a) 
//VALUE self = rb_class_new_instance(n, argv, klass);

// (b)
VALUE self = rb_funcall2(klass, rb_intern("new"), n, argv); 

As you can see there is two ways to instantiate (a) or (b).

···

On Thu, 24 Apr 2003 19:29:39 +0000, Phil Tomson wrote:

In article 006b01c30a8e$5b24ad70$6401a8c0@MELONBALLER,
Chris Pine nemo@hellotree.com wrote:

Maybe I’m not understanding, but can’t you just call `new’ on the class you
want to instantiate?

I want to call ‘new’ on the class on the C side. The more I think about
it, the more I doubt this is possible.


Simon Strandgaard

In article b89f690f5u@enews4.newsguy.com,

In article 007c01c30a90$9e798bc0$6401a8c0@MELONBALLER,

From: “Chris Pine” nemo@hellotree.com

Maybe I’m not understanding, but can’t you just call `new’ on the class you
want to instantiate?

Sorry if that was too short as to be unhelpful. What I meant was that, if
you have the class object on the C side, you can just call `new’ on it with
one of these:

rb_funcall
rb_funcall2
rb_funcall3
rb_apply

You will need to get the id for `new’ first, with this:

new_id = rb_intern (“new”);

Most of this is on page 193 of the pickaxe.

Or, you could just do this (which is slower):

rb_eval_string (“YourRubyClass.new”);

Hmmmm… but how does the C side ‘know’ where my Ruby class is defined?
There doesn’t seem to be a ‘rb_require’. I guess I should just try it
out. I suppose if on the Ruby side I’ve got:

require ‘SomeClass’
require ‘MyCExtention’

That perhaps MyCExtention might then have access to SomeClass (?)

OK, I tried it and that is how it seems to work.

It seems like to call the constructor of a Ruby class from C that you
have to use rb_eval_string(“YourRubyClass.new”); I don’t see how you
could do it otherwise since rb_funcall needs a receiver and you don’t yet
have a reciever:

rb_funcall(VALUE recv, ID id, int argc, …);

So how would you call Foo.new using rb_funcall? You’d have to get the ID:
rb_intern(“Foo.new”);
But then what would you use for recv?

At any rate, rb_eval_string is working fine for me.

Phil

···

Phil Tomson ptkwt@shell1.aracnet.com wrote:

Chris Pine nemo@hellotree.com wrote:

----- Original Message -----

In article pan.2003.04.24.21.30.41.715600@sneakemail.com,

···

Simon Strandgaard 0bz63fz3m1qt3001@sneakemail.com wrote:

On Thu, 24 Apr 2003 19:29:39 +0000, Phil Tomson wrote:

In article 006b01c30a8e$5b24ad70$6401a8c0@MELONBALLER,
Chris Pine nemo@hellotree.com wrote:

Maybe I’m not understanding, but can’t you just call `new’ on the class you
want to instantiate?

I want to call ‘new’ on the class on the C side. The more I think about
it, the more I doubt this is possible.

Its possible, I do it myself all the time.

char *name_of_class = “test”;
VALUE klass = rb_const_get(rb_cObject, rb_intern(name_of_class));

// (a)
//VALUE self = rb_class_new_instance(n, argv, klass);

// (b)
VALUE self = rb_funcall2(klass, rb_intern(“new”), n, argv);

As you can see there is two ways to instantiate (a) or (b).

Thanks. There’s also a third way using rb_eval_string. Now I see how you
can use rb_funcall to instantiate a new object (use rb_const_get).

Phil

Hi,

char *name_of_class = “test”;
“Test”;

Class name must be a constant name.

VALUE klass = rb_const_get(rb_cObject, rb_intern(name_of_class));

Or:
VALUE klass = rb_path2class(name_of_class);

This can handle nested classes.

···

At Fri, 25 Apr 2003 06:34:24 +0900, Simon Strandgaard wrote:


Nobu Nakada

It seems like to call the constructor of a Ruby class from C that you
have to use rb_eval_string(“YourRubyClass.new”); I don’t see how you
could do it otherwise since rb_funcall needs a receiver and you don’t yet
have a reciever:

rb_funcall(VALUE recv, ID id, int argc, …);

So how would you call Foo.new using rb_funcall? You’d have to get the ID:
rb_intern(“Foo.new”);
But then what would you use for recv?

You can get the value of constant “Foo” (seems like rb_gv_get() will do the
job, I may be mistaken) and use it as a receiver.

At any rate, rb_eval_string is working fine for me.

Phil

Gennady.

···

----- Original Message -----
From: “Phil Tomson” ptkwt@shell1.aracnet.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, April 24, 2003 2:33 PM
Subject: Re: Accessing Ruby class from C extention

It seems like to call the constructor of a Ruby class from C that you
have to use rb_eval_string(“YourRubyClass.new”); I don’t see how you
could do it otherwise since rb_funcall needs a receiver and you don’t yet
have a reciever:

rb_funcall(VALUE recv, ID id, int argc, …);

So how would you call Foo.new using rb_funcall? You’d have to get the ID:
rb_intern(“Foo.new”);
But then what would you use for recv?

···

----- Original Message -----
From: “Phil Tomson” ptkwt@shell1.aracnet.com


I think the id is basically the symbol; so you only want the id for “new”,
not for “Foo.new”. To get the recv, I think you can use the C version of:

Object.const_get “YourClassName”

which is probably something like rb_const_get… make sure you intern your
strings!

Chris

char *name_of_class = “test”;
“Test”;

agree

Class name must be a constant name.

VALUE klass = rb_const_get(rb_cObject, rb_intern(name_of_class));

Or:
VALUE klass = rb_path2class(name_of_class);

This can handle nested classes.

Kool! I wasn’t aware of this…
I will right away add this to my embedding-tutorial :slight_smile:

···

On Fri, 25 Apr 2003 10:59:32 +0900, nobu.nokad wrote:

At Fri, 25 Apr 2003 06:34:24 +0900, Simon Strandgaard wrote:


Simon Strandgaard

From: “Phil Tomson” ptkwt@shell1.aracnet.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, April 24, 2003 2:33 PM
Subject: Re: Accessing Ruby class from C extention

It seems like to call the constructor of a Ruby class from C that you
have to use rb_eval_string(“YourRubyClass.new”); I don’t see how you
could do it otherwise since rb_funcall needs a receiver and you don’t
yet
have a reciever:

rb_funcall(VALUE recv, ID id, int argc, …);

So how would you call Foo.new using rb_funcall? You’d have to get the
ID:
rb_intern(“Foo.new”);
But then what would you use for recv?

You can get the value of constant “Foo” (seems like rb_gv_get() will do
the
job, I may be mistaken) and use it as a receiver.

I mean, as a receiver for “new”.

···

----- Original Message -----
From: “Gennady” gfb@tonesoft.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, April 24, 2003 3:34 PM
Subject: Re: Accessing Ruby class from C extention

----- Original Message -----

At any rate, rb_eval_string is working fine for me.

Phil

Gennady.

Hi Simon,

In article pan.2003.04.25.01.25.19.239020@sneakemail.com, Simon
Strandgaard wrote:

VALUE klass = rb_path2class(name_of_class);

This can handle nested classes.

Kool! I wasn’t aware of this…
I will right away add this to my embedding-tutorial :slight_smile:

Is your tutorial online? I did a quick google search for it, but could find
nothing. If it is online I would really like to read it (in that case is
there a URL?).

Take care, Matthew

···


A friend is someone who knows everything about you and likes you in
spite of it.
-Mark Twain

In article pan.2003.04.25.01.25.19.239020@sneakemail.com, Simon
Strandgaard wrote:

VALUE klass = rb_path2class(name_of_class);

This can handle nested classes.

Kool! I wasn’t aware of this…
I will right away add this to my embedding-tutorial :slight_smile:

Is your tutorial online? I did a quick google search for it, but could find
nothing. If it is online I would really like to read it (in that case is
there a URL?).

http://metaeditor.sf.net/embed/

Take care, Matthew

I will :slight_smile:

···

On Sat, 03 May 2003 15:26:51 +0000, Matthew Miller wrote: