Creating a reference to a ruby variable in a C extension.

Discussion in 'Ruby' started by Christer Sandberg, Sep 20, 2006.

  1. Hi!

    I'm just making my first C extension and have a question about creating
    a reference to a ruby variable, that's passed as a method parameter to
    my C
    equivalent of initialize. I need this variable to be available after the
    method has exited because I wan't to call methods on the class
    represented by that variable.

    This is what I've done so far after reading the README.EXT etc,

    static VALUE ref;

    /* The initialize method. */
    static VALUE init(VALUE self, VALUE arg)
    {
    ...
    ref = arg;
    rb_global_variable(&ref);
    }

    Then later on I wan't to use it like this:

    void call(void)
    {
    rb_funcall(ref, rb_intern("some_method"), 0, 0);
    }

    Is this the right way to do it or should I solve the problem in another
    way?

    Greatful for a fast reply!

    Thanx
    Christer

    --
    Posted via http://www.ruby-forum.com/.
     
    Christer Sandberg, Sep 20, 2006
    #1
    1. Advertising

  2. Hello !

    > Then later on I wan't to use it like this:
    >
    > void call(void)
    > {
    > rb_funcall(ref, rb_intern("some_method"), 0, 0);
    > }


    How comes this function has no parameters ? Is it being called from
    ruby, or only from C code ?

    I tend to think that using global variables is not a really good idea.
    We need a bit more context about what you want to do. Is it a class ?
    Will it have several instances ?

    In the latter case, have a look at rb_iv_get and rb_iv_set to get/set
    instance variables of a class instance, something like

    rb_iv_set(self, rb_intern("@variable"), arg); /* in init(...) */

    and


    rb_funcall(rb_iv_get(self,rb_intern("@variable")),rb_intern("some_method"),
    0, 0); /* in call */

    Don't forget as well that every single C function that can be called
    directly from ruby should probably have at least one VALUE parameter and
    *must* return a VALUE.

    Cheers !

    Vince
     
    Vincent Fourmond, Sep 20, 2006
    #2
    1. Advertising

  3. Re: Creating a reference to a ruby variable in a C extension

    Vincent Fourmond wrote:
    > Hello !
    >
    >> Then later on I wan't to use it like this:
    >>
    >> void call(void)
    >> {
    >> rb_funcall(ref, rb_intern("some_method"), 0, 0);
    >> }

    >
    > How comes this function has no parameters ? Is it being called from
    > ruby, or only from C code ?
    >


    Thank you for the reply, I'll try to clear things up a bit and explain
    what I want to do.

    The function is just an example for the sake of making my question a bit
    clearer. The real functions I am using has parameters. Those functions
    such as the one above will only be called from C code.

    >
    > I tend to think that using global variables is not a really good idea.
    > We need a bit more context about what you want to do. Is it a class ?
    > Will it have several instances ?
    >
    > In the latter case, have a look at rb_iv_get and rb_iv_set to get/set
    > instance variables of a class instance, something like
    >
    > rb_iv_set(self, rb_intern("@variable"), arg); /* in init(...) */
    >
    > and
    >
    >
    > rb_funcall(rb_iv_get(self,rb_intern("@variable")),rb_intern("some_method"),
    > 0, 0); /* in call */
    >


    Yes, I'm writing a tiny Ruby class in C that wraps and uses a bison/flex
    generated parser. The saved variable reference will be used for making
    calls on the ruby instance. When those calls are made self is long gone
    out of scope sice it's the parser who triggers the method call. The C
    Ruby class just acts as a proxy or adapter between the parser and the
    Ruby object.

    > Don't forget as well that every single C function that can be called
    > directly from ruby should probably have at least one VALUE parameter and
    > *must* return a VALUE.
    >
    > Cheers !
    >
    > Vince


    As mentioned above, it's not invoked from Ruby.


    Thanx again, Christer.

    --
    Posted via http://www.ruby-forum.com/.
     
    Christer Sandberg, Sep 21, 2006
    #3
  4. Re: Creating a reference to a ruby variable in a C extension

    On 9/21/06, Christer Sandberg <> wrote:
    > Vincent Fourmond wrote:
    > > Hello !
    > >
    > >> Then later on I wan't to use it like this:
    > >>
    > >> void call(void)
    > >> {
    > >> rb_funcall(ref, rb_intern("some_method"), 0, 0);
    > >> }

    > >
    > > How comes this function has no parameters ? Is it being called from
    > > ruby, or only from C code ?
    > >

    >
    > Thank you for the reply, I'll try to clear things up a bit and explain
    > what I want to do.
    >
    > The function is just an example for the sake of making my question a bit
    > clearer. The real functions I am using has parameters. Those functions
    > such as the one above will only be called from C code.
    >
    > >
    > > I tend to think that using global variables is not a really good idea.
    > > We need a bit more context about what you want to do. Is it a class ?
    > > Will it have several instances ?
    > >
    > > In the latter case, have a look at rb_iv_get and rb_iv_set to get/set
    > > instance variables of a class instance, something like
    > >
    > > rb_iv_set(self, rb_intern("@variable"), arg); /* in init(...) */
    > >
    > > and
    > >
    > >
    > > rb_funcall(rb_iv_get(self,rb_intern("@variable")),rb_intern("some_method"),
    > > 0, 0); /* in call */
    > >

    >
    > Yes, I'm writing a tiny Ruby class in C that wraps and uses a bison/flex
    > generated parser. The saved variable reference will be used for making
    > calls on the ruby instance. When those calls are made self is long gone
    > out of scope sice it's the parser who triggers the method call. The C
    > Ruby class just acts as a proxy or adapter between the parser and the
    > Ruby object.


    Hi Christer,

    Instead of saving it as a global variable, you could save it as a
    class variable. See rb_cvar_[gs]et (defined in variable.c). Just an
    idea.

    Cheers,
    Dave
     
    David Balmain, Sep 21, 2006
    #4
  5. Re: Creating a reference to a ruby variable in a C extension

    David Balmain wrote:
    > On 9/21/06, Christer Sandberg <> wrote:
    >> Vincent Fourmond wrote:
    >> > Hello !
    >> >
    >> >> Then later on I wan't to use it like this:
    >> >>
    >> >> void call(void)
    >> >> {
    >> >> rb_funcall(ref, rb_intern("some_method"), 0, 0);
    >> >> }
    >> >
    >> > How comes this function has no parameters ? Is it being called from
    >> > ruby, or only from C code ?
    >> >

    >>
    >> Thank you for the reply, I'll try to clear things up a bit and explain
    >> what I want to do.
    >>
    >> The function is just an example for the sake of making my question a bit
    >> clearer. The real functions I am using has parameters. Those functions
    >> such as the one above will only be called from C code.
    >>
    >> >
    >> > I tend to think that using global variables is not a really good

    >> idea.
    >> > We need a bit more context about what you want to do. Is it a class ?
    >> > Will it have several instances ?
    >> >
    >> > In the latter case, have a look at rb_iv_get and rb_iv_set to get/set
    >> > instance variables of a class instance, something like
    >> >
    >> > rb_iv_set(self, rb_intern("@variable"), arg); /* in init(...) */
    >> >
    >> > and
    >> >
    >> >
    >> >

    >> rb_funcall(rb_iv_get(self,rb_intern("@variable")),rb_intern("some_method"),
    >>
    >> > 0, 0); /* in call */
    >> >

    >>
    >> Yes, I'm writing a tiny Ruby class in C that wraps and uses a bison/flex
    >> generated parser. The saved variable reference will be used for making
    >> calls on the ruby instance. When those calls are made self is long gone
    >> out of scope sice it's the parser who triggers the method call. The C
    >> Ruby class just acts as a proxy or adapter between the parser and the
    >> Ruby object.

    >
    > Hi Christer,
    >
    > Instead of saving it as a global variable, you could save it as a
    > class variable. See rb_cvar_[gs]et (defined in variable.c). Just an
    > idea.
    >
    > Cheers,
    > Dave
    >


    Hi Dave!

    That would work if the passed in object should be shared among all
    instances of my class, but that's not the case since it's a callback
    object that's supplied for a particular instance of my class.

    Correct me if I'm wrong but the variable is only global in my C code
    since I haven't made it visible to the Ruby environment with a
    rb_gv_set(const char *name, VALUE value)?

    Thanx
    Christer
     
    Christer Sandberg, Sep 21, 2006
    #5
  6. Re: Creating a reference to a ruby variable in a C extension

    On 9/21/06, Christer Sandberg <> wrote:
    > David Balmain wrote:
    > > On 9/21/06, Christer Sandberg <> wrote:
    > >> Vincent Fourmond wrote:
    > >> > Hello !
    > >> >
    > >> >> Then later on I wan't to use it like this:
    > >> >>
    > >> >> void call(void)
    > >> >> {
    > >> >> rb_funcall(ref, rb_intern("some_method"), 0, 0);
    > >> >> }
    > >> >
    > >> > How comes this function has no parameters ? Is it being called from
    > >> > ruby, or only from C code ?
    > >> >
    > >>
    > >> Thank you for the reply, I'll try to clear things up a bit and explain
    > >> what I want to do.
    > >>
    > >> The function is just an example for the sake of making my question a bit
    > >> clearer. The real functions I am using has parameters. Those functions
    > >> such as the one above will only be called from C code.
    > >>
    > >> >
    > >> > I tend to think that using global variables is not a really good
    > >> idea.
    > >> > We need a bit more context about what you want to do. Is it a class ?
    > >> > Will it have several instances ?
    > >> >
    > >> > In the latter case, have a look at rb_iv_get and rb_iv_set to get/set
    > >> > instance variables of a class instance, something like
    > >> >
    > >> > rb_iv_set(self, rb_intern("@variable"), arg); /* in init(...) */
    > >> >
    > >> > and
    > >> >
    > >> >
    > >> >
    > >> rb_funcall(rb_iv_get(self,rb_intern("@variable")),rb_intern("some_method"),
    > >>
    > >> > 0, 0); /* in call */
    > >> >
    > >>
    > >> Yes, I'm writing a tiny Ruby class in C that wraps and uses a bison/flex
    > >> generated parser. The saved variable reference will be used for making
    > >> calls on the ruby instance. When those calls are made self is long gone
    > >> out of scope sice it's the parser who triggers the method call. The C
    > >> Ruby class just acts as a proxy or adapter between the parser and the
    > >> Ruby object.

    > >
    > > Hi Christer,
    > >
    > > Instead of saving it as a global variable, you could save it as a
    > > class variable. See rb_cvar_[gs]et (defined in variable.c). Just an
    > > idea.
    > >
    > > Cheers,
    > > Dave
    > >

    >
    > Hi Dave!
    >
    > That would work if the passed in object should be shared among all
    > instances of my class, but that's not the case since it's a callback
    > object that's supplied for a particular instance of my class.
    >
    > Correct me if I'm wrong but the variable is only global in my C code
    > since I haven't made it visible to the Ruby environment with a
    > rb_gv_set(const char *name, VALUE value)?
    >
    > Thanx
    > Christer


    Hi Christer,

    Right you are. I can't believe I haven't looked at this method before.
    rb_global_variable simply registers the object so that it won't be
    garbage collected. Incidentally for those interested,
    rb_global_variable is really just an alias for rb_gc_register_address.
    If you later want to let the object to be garbage collected you just
    need to call rb_gc_unregister_address(&value). I wish I knew about
    this a couple of months ago.

    Anyway, now that I know this I think the way you are going about
    solving the problem is the correct one.

    Thanks,
    Dave
     
    David Balmain, Sep 21, 2006
    #6
  7. Re: Creating a reference to a ruby variable in a C extension

    David Balmain wrote:
    > On 9/21/06, Christer Sandberg <> wrote:
    >> David Balmain wrote:
    >> > On 9/21/06, Christer Sandberg <> wrote:
    >> >> Vincent Fourmond wrote:
    >> >> > Hello !
    >> >> >
    >> >> >> Then later on I wan't to use it like this:
    >> >> >>
    >> >> >> void call(void)
    >> >> >> {
    >> >> >> rb_funcall(ref, rb_intern("some_method"), 0, 0);
    >> >> >> }
    >> >> >
    >> >> > How comes this function has no parameters ? Is it being called

    >> from
    >> >> > ruby, or only from C code ?
    >> >> >
    >> >>
    >> >> Thank you for the reply, I'll try to clear things up a bit and explain
    >> >> what I want to do.
    >> >>
    >> >> The function is just an example for the sake of making my question

    >> a bit
    >> >> clearer. The real functions I am using has parameters. Those functions
    >> >> such as the one above will only be called from C code.
    >> >>
    >> >> >
    >> >> > I tend to think that using global variables is not a really good
    >> >> idea.
    >> >> > We need a bit more context about what you want to do. Is it a

    >> class ?
    >> >> > Will it have several instances ?
    >> >> >
    >> >> > In the latter case, have a look at rb_iv_get and rb_iv_set to

    >> get/set
    >> >> > instance variables of a class instance, something like
    >> >> >
    >> >> > rb_iv_set(self, rb_intern("@variable"), arg); /* in init(...) */
    >> >> >
    >> >> > and
    >> >> >
    >> >> >
    >> >> >
    >> >>

    >> rb_funcall(rb_iv_get(self,rb_intern("@variable")),rb_intern("some_method"),
    >>
    >> >>
    >> >> > 0, 0); /* in call */
    >> >> >
    >> >>
    >> >> Yes, I'm writing a tiny Ruby class in C that wraps and uses a

    >> bison/flex
    >> >> generated parser. The saved variable reference will be used for making
    >> >> calls on the ruby instance. When those calls are made self is long

    >> gone
    >> >> out of scope sice it's the parser who triggers the method call. The C
    >> >> Ruby class just acts as a proxy or adapter between the parser and the
    >> >> Ruby object.
    >> >
    >> > Hi Christer,
    >> >
    >> > Instead of saving it as a global variable, you could save it as a
    >> > class variable. See rb_cvar_[gs]et (defined in variable.c). Just an
    >> > idea.
    >> >
    >> > Cheers,
    >> > Dave
    >> >

    >>
    >> Hi Dave!
    >>
    >> That would work if the passed in object should be shared among all
    >> instances of my class, but that's not the case since it's a callback
    >> object that's supplied for a particular instance of my class.
    >>
    >> Correct me if I'm wrong but the variable is only global in my C code
    >> since I haven't made it visible to the Ruby environment with a
    >> rb_gv_set(const char *name, VALUE value)?
    >>
    >> Thanx
    >> Christer

    >
    > Hi Christer,
    >
    > Right you are. I can't believe I haven't looked at this method before.
    > rb_global_variable simply registers the object so that it won't be
    > garbage collected. Incidentally for those interested,
    > rb_global_variable is really just an alias for rb_gc_register_address.
    > If you later want to let the object to be garbage collected you just
    > need to call rb_gc_unregister_address(&value). I wish I knew about
    > this a couple of months ago.
    >
    > Anyway, now that I know this I think the way you are going about
    > solving the problem is the correct one.
    >
    > Thanks,
    > Dave
    >


    Alright...

    Didn't know about that method (rb_gc_unregister_address(&value);),
    thanks Dave!

    Christer
     
    Christer Sandberg, Sep 21, 2006
    #7
  8. Re: Creating a reference to a ruby variable in a C extension

    [I posted that yesterday lunch time, and it didn't get on the archive
    yet, so I'm posting that again.]

    Hello !

    > That would work if the passed in object should be shared among all
    > instances of my class, but that's not the case since it's a
    > callback object that's supplied for a particular instance of my class.
    > Correct me if I'm wrong but the variable is only global in my C
    > code since I haven't made it visible to the Ruby environment with a
    > rb_gv_set(const char *name, VALUE value)?


    Ooops... Unless I completely didn't get you right, you're going right
    into troubles. There will always be one instance of your C variable. So
    if you have several instances of your class, then everytime you use one,
    you will actually use the reference that you stored in the last instance
    created... it will all go wrong. I just can't understand why your 'self'
    will be gone out of scope. Do you destroy quickly the instances of your
    class ? But then, how do you expect to have a per-instance storage if
    you destroy the instances ?

    Cheers !

    Vince
     
    Vincent Fourmond, Sep 22, 2006
    #8
  9. Christer Sandberg

    Guest

    Re: Creating a reference to a ruby variable in a C extension

    Quoting Vincent Fourmond <>:

    > [I posted that yesterday lunch time, and it didn't get on the archive
    > yet, so I'm posting that again.]
    >
    > Hello !
    >
    >> That would work if the passed in object should be shared among all
    >> instances of my class, but that's not the case since it's a
    >> callback object that's supplied for a particular instance of my class.
    >> Correct me if I'm wrong but the variable is only global in my C
    >> code since I haven't made it visible to the Ruby environment with a
    >> rb_gv_set(const char *name, VALUE value)?

    >
    > Ooops... Unless I completely didn't get you right, you're going right
    > into troubles. There will always be one instance of your C variable. So
    > if you have several instances of your class, then everytime you use one,
    > you will actually use the reference that you stored in the last instance
    > created... it will all go wrong. I just can't understand why your 'self'
    > will be gone out of scope. Do you destroy quickly the instances of your
    > class ? But then, how do you expect to have a per-instance storage if
    > you destroy the instances ?
    >
    > Cheers !
    >
    > =09Vince
    >
    >
    >


    Hi Vince!

    Of course, you are totally right!

    The issue with self not being available was that I was calling =20
    yyparse() and hadn't configured bison so that yyparse was given any =20
    parameters, hence self wasn't available in the parser code. I didn't =20
    destroy it just couldn't reach it. Now I have taken a different =20
    aproach. yyparse is called with a parameter and instead of passing the =20
    callback instance as a parameter to initialize I have made it a =20
    class/module method instead, since the only task for my extension is =20
    to delegate the parsing routine.

    Thanks again, though, for opening my eyes. There's been a long time =20
    since I wrote some C code and I didn't think about this.

    /Christer
     
    , Sep 22, 2006
    #9
  10. Re: Creating a reference to a ruby variable in a C extension

    Hello !

    > The issue with self not being available was that I was calling yyparse()
    > and hadn't configured bison so that yyparse was given any parameters,
    > hence self wasn't available in the parser code. I didn't destroy it just
    > couldn't reach it. Now I have taken a different aproach. yyparse is
    > called with a parameter and instead of passing the callback instance as
    > a parameter to initialize I have made it a class/module method instead,
    > since the only task for my extension is to delegate the parsing routine.


    Yes, bison and flex always give great fun. Just out of curiosity, what
    are you parsing ?

    > Thanks again, though, for opening my eyes. There's been a long time
    > since I wrote some C code and I didn't think about this.


    I did bump into this not so long ago... I'd rather you didn't ;-) !

    Vince
     
    Vincent Fourmond, Sep 22, 2006
    #10
  11. Re: Creating a reference to a ruby variable in a C extension

    Vincent Fourmond wrote:
    > Hello !
    >
    >> The issue with self not being available was that I was calling yyparse()
    >> and hadn't configured bison so that yyparse was given any parameters,
    >> hence self wasn't available in the parser code. I didn't destroy it just
    >> couldn't reach it. Now I have taken a different aproach. yyparse is
    >> called with a parameter and instead of passing the callback instance as
    >> a parameter to initialize I have made it a class/module method instead,
    >> since the only task for my extension is to delegate the parsing routine.

    >
    > Yes, bison and flex always give great fun. Just out of curiosity, what
    > are you parsing ?
    >
    >> Thanks again, though, for opening my eyes. There's been a long time
    >> since I wrote some C code and I didn't think about this.

    >
    > I did bump into this not so long ago... I'd rather you didn't ;-) !
    >
    > Vince


    Hi again, Vince!

    Maybe I'm well deep over my head here, but my goal is to
    modify/customize the CSS parser/lexer used by KDE and Apple (in Safari)
    and wrap it up as a Ruby extension. My first thing on the TODO list is
    making an implementation of the SAC API, and then move on to make a DOM
    implementation built upon the SAC API. My extension is calling back to a
    document handler SAC implementation which I will make as a module to be
    able to override only the methods interesting if one might want to make
    a customized handling or implementation.

    Actually, this idea came to my mind when thinking about doing a Ruby
    Markdown to PDF conversion utility. Then I thought that one should be
    able to customize the fonts, colors etc, and since Markdown converts to
    XHTML and CSS can be used to style that... Well, you get the point.

    Cheers,
    Christer

    --
    Posted via http://www.ruby-forum.com/.
     
    Christer Sandberg, Sep 22, 2006
    #11
  12. Re: Creating a reference to a ruby variable in a C extension

    On 9/23/06, Christer Sandberg <> wrote:
    > Vincent Fourmond wrote:
    > > Hello !
    > >
    > >> The issue with self not being available was that I was calling yyparse()
    > >> and hadn't configured bison so that yyparse was given any parameters,
    > >> hence self wasn't available in the parser code. I didn't destroy it just
    > >> couldn't reach it. Now I have taken a different aproach. yyparse is
    > >> called with a parameter and instead of passing the callback instance as
    > >> a parameter to initialize I have made it a class/module method instead,
    > >> since the only task for my extension is to delegate the parsing routine.

    > >
    > > Yes, bison and flex always give great fun. Just out of curiosity, what
    > > are you parsing ?
    > >
    > >> Thanks again, though, for opening my eyes. There's been a long time
    > >> since I wrote some C code and I didn't think about this.

    > >
    > > I did bump into this not so long ago... I'd rather you didn't ;-) !
    > >
    > > Vince

    >
    > Hi again, Vince!
    >
    > Maybe I'm well deep over my head here, but my goal is to
    > modify/customize the CSS parser/lexer used by KDE and Apple (in Safari)
    > and wrap it up as a Ruby extension. My first thing on the TODO list is
    > making an implementation of the SAC API, and then move on to make a DOM
    > implementation built upon the SAC API. My extension is calling back to a
    > document handler SAC implementation which I will make as a module to be
    > able to override only the methods interesting if one might want to make
    > a customized handling or implementation.
    >
    > Actually, this idea came to my mind when thinking about doing a Ruby
    > Markdown to PDF conversion utility. Then I thought that one should be
    > able to customize the fonts, colors etc, and since Markdown converts to
    > XHTML and CSS can be used to style that... Well, you get the point.
    >
    > Cheers,
    > Christer
    >


    Hey Christer,

    This sounds like an interesting project. Is it going to be open
    source? I could definitely use something like this.

    cheers,
    Dave
     
    David Balmain, Sep 23, 2006
    #12
  13. Re: Creating a reference to a ruby variable in a C extension

    David Balmain wrote:
    > On 9/23/06, Christer Sandberg <> wrote:
    >> >

    >> Hi again, Vince!
    >> Actually, this idea came to my mind when thinking about doing a Ruby
    >> Markdown to PDF conversion utility. Then I thought that one should be
    >> able to customize the fonts, colors etc, and since Markdown converts to
    >> XHTML and CSS can be used to style that... Well, you get the point.
    >>
    >> Cheers,
    >> Christer
    >>

    >
    > Hey Christer,
    >
    > This sounds like an interesting project. Is it going to be open
    > source? I could definitely use something like this.
    >
    > cheers,
    > Dave


    Hi David!

    Well, whatever I may release will be open source. It all depends on how
    much time I can put into it since I have a full day job etc. The CSS
    part is my main concern, I think this is a missing piece in the Ruby
    world. Maybe I'll put up a project at rubyforge before it's finished and
    see if there's someone who's interested in helping out. I have my other
    project http://rubyforge.org/projects/hessian to look out for as well,
    but it's a kind of (don't know the english word) narrow technology and
    dosen't take to much time at the moment, so we'll see.

    Christer


    --
    Posted via http://www.ruby-forum.com/.
     
    Christer Sandberg, Sep 24, 2006
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matthew Miller
    Replies:
    2
    Views:
    121
    Matthew Miller
    Sep 29, 2003
  2. Nicholas
    Replies:
    3
    Views:
    388
    Ryan Davis
    Jan 28, 2007
  3. David Simas

    A C++ reference in a Ruby extension

    David Simas, Apr 12, 2007, in forum: Ruby
    Replies:
    2
    Views:
    87
    Joel VanderWerf
    Apr 12, 2007
  4. Iñaki Baz Castillo
    Replies:
    7
    Views:
    227
    Iñaki Baz Castillo
    Oct 22, 2009
  5. Iñaki Baz Castillo
    Replies:
    2
    Views:
    228
    Iñaki Baz Castillo
    Apr 20, 2011
Loading...

Share This Page