C extension: can rb_ivar_set be used to set class variable?

L

lianliming

Hi all,

This is a question on Ruby C extension.

I have been hacking some existed ruby c extension, and found following
code:

VALUE klass = rb_define_class(name, pClass);
rb_ivar_set(klass, id_some_var, someValue);

From the book "Programming Ruby, Second Edition", I know the prototype
for rb_ivar_set is like:

VALUE rb_ivar_set( VALUE obj, ID name, VALUE value )

And it says the first parameter should be an obj, while as we can see
from above, the code I am hacking is passing "klass" returned by
rb_define_class to rb_ivar_set.

So I wonder if this is a way to set class variable for a class. I am
really confused because the document says it should be used to set
value of instance variable to a given obj. Am I missing some
knowledge?

Any help is appreciated and thanks in advance!
 
N

Nobuyoshi Nakada

Hi,

At Fri, 14 Dec 2007 14:20:01 +0900,
lianliming wrote in [ruby-talk:283492]:
So I wonder if this is a way to set class variable for a class. I am
really confused because the document says it should be used to set
value of instance variable to a given obj. Am I missing some
knowledge?

No, use rb_cvar_set to set class variables. rb_ivar_set sets
an instance variable of a class instance. I.E.,

class Foo
@foo = "ivar"
@@foo = "cvar"
end
 
L

lianliming

Thanks for your reply!
No, use rb_cvar_set to set class variables. rb_ivar_set sets
an instance variable of a class instance. I.E.,

class Foo
@foo = "ivar"
@@foo = "cvar"
end

Will the instance variable "@foo"'s value declared as the above
example can be referenced in an object of Class Foo?

Please look at following example:

class Foo
@foo = "ivar"

def printFoo
puts @foo
end
end

f=Foo.new
f.printFoo
========> nil

So now, I am curious to know, why the function rb_ivar_set allows
passing a "klass" as the first parameter to set value of a instance
variable which can't be referenced by its objects.
 
N

Nobuyoshi Nakada

Hi,

At Fri, 14 Dec 2007 15:15:02 +0900,
lianliming wrote in [ruby-talk:283498]:
Will the instance variable "@foo"'s value declared as the above
example can be referenced in an object of Class Foo?

No, two different objects's instance variables.

Now your question is not related to C extension. I guess
others could explain it much better than me.
 
R

Rick DeNatale

Thanks for your reply!


Will the instance variable "@foo"'s value declared as the above
example can be referenced in an object of Class Foo?

Please look at following example:

class Foo
@foo = "ivar"

def printFoo
puts @foo
end
end

f=Foo.new
f.printFoo
========> nil

So now, I am curious to know, why the function rb_ivar_set allows
passing a "klass" as the first parameter to set value of a instance
variable which can't be referenced by its objects.

rb_ivar_set takes an object as the first parameter. Classes are
objects, and as such can have their own instance variables which are
visible in class methods. These are called class instance variables,
and are quite different from class variables. Being instance
variables, class instance variables are only visible to methods of the
object to which they are attached, which in the case of class instance
variables would be class methods.

There's also a subtlety to the Ruby object model which can be
surprising to folks familiar with other OO languages. In many
languages including Java, C++ and Smalltalk, one of the functions of a
class is to serve as a template which maps the layout of the object in
memory, in a manner analogous to a C struct, so that method code can
reference instance variables by offset from the address of the
instance. Ruby classes don't really "know" about the instance
variables of their instances, since instance variables( actually all
variables) aren't declared in Ruby. Instance variables get attached
to an instance dynamically when a method is executed which mentions
that instance variable. In fact different instances of the same class
can have different sets of instance variables, and the set of instance
variables of a particular object can change over time.

Conceptually, and actually at least for Matz's Ruby Implementation,
instance variables are resolved by accessing a per-instance internal
hash table which maps the instance variable name (including the @
sigil) as a symbol to the value.

Class variables, marked with the @@ sigil are also looked up in a hash
associated with the class object. The difference is that for class
variables, if the key is not found in the hash, the search considers
iteratively up the superclass chain, and for class methods, it's the
class and not the metaclass chain which is traversed. This means that
class variables are visible to both instance and class methods of the
class where they live and that classes subclasses. The MRI, at least
the last time I looked, actually puts class variables in the same hash
as class instance variables, i.e. the class objects instance variable
hash. It's the difference in the sigils which affects how they are
seen and used.
 
H

Heath Novak

unsubscribe
Hi,

At Fri, 14 Dec 2007 14:20:01 +0900,
lianliming wrote in [ruby-talk:283492]:
So I wonder if this is a way to set class variable for a class. I am
really confused because the document says it should be used to set
value of instance variable to a given obj. Am I missing some
knowledge?

No, use rb_cvar_set to set class variables. rb_ivar_set sets
an instance variable of a class instance. I.E.,

class Foo
@foo = "ivar"
@@foo = "cvar"
end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top