I'm stuck

Well my problem sounds IMHO trivial.

assume I have a ruby file like that

class SomeClass

    @@some_var = 0;

end

Now I want to create an this Object from C and access
@@some_var

How do I do that?

I tried a day, but do not get more far than access violations
I checked Google and read the Ruby chapter in the Programming Ruby
book more than once, but did not get it. So please give me a hand

Friedrich

Hi,

someclass.c (408 Bytes)

someclass.rb (185 Bytes)

···

At Fri, 28 Feb 2003 18:02:53 +0900, Friedrich Dominicus wrote:

assume I have a ruby file like that

class SomeClass

    @@some_var = 0;

end

Now I want to create an this Object from C and access
@@some_var

rb_cvar_get() or rb_cv_get(). The former accepts ID and name
for the latter.

nobu.nokada@softhome.net writes:

–Multipart_Fri_Feb_28_19:22:32_2003-1
Content-Type: text/plain; charset=US-ASCII

Hi,

assume I have a ruby file like that

class SomeClass

    @@some_var = 0;

end

Now I want to create an this Object from C and access
@@some_var

rb_cvar_get() or rb_cv_get(). The former accepts ID and name
for the latter.
Well it’s a bit different (as I found out myself short after my
posting)

–Multipart_Fri_Feb_28_19:22:32_2003-1
Content-Type: text/c-src; charset=US-ASCII
Content-Disposition: attachment; filename=“someclass.c”
Content-Transfer-Encoding: 7bit

#include “ruby.h”

static VALUE
some_s_var(VALUE klass)
{
return rb_cv_get(klass, “@@some_var”);
}

static VALUE
some_var(VALUE self)
{
return some_s_var(CLASS_OF(self));
}

void
Init_someclass()
{
VALUE someclass = rb_const_get(rb_cObject, rb_intern(“SomeClass”));
rb_define_method(someclass, “some_var”, some_var, 0);
rb_define_singleton_method(someclass, “some_var”, some_s_var, 0);
}
This is not what I wanted ot do I just wanted to use the Ruby stuff
directly no C extension library.

Here’s what I have come up with

class T1
@@some_var = [ “String1”,
“String2”,
“String3”]
end

/* Generated header

  • File Name : t1.c
···

At Fri, 28 Feb 2003 18:02:53 +0900, > Friedrich Dominicus wrote:

  • Created : 2003-02-28 09:57:47 frido
  • Author : Friedrich Dominicus
  • Time-stamp: <>
    */

#include <ruby.h>
#include <stdio.h>

int main (void){
int i;
VALUE obj;
VALUE klass;
ruby_init(); /* embed Ruby into this program! /
/
uby_script(“embed”);
rb_load_file(“t1.rb”); /
obj = rb_eval_string(“load ‘t1.rb’”);
/
question why does rb_load_file does not work? /
klass = rb_const_get(rb_cObject, rb_intern(“T1”));
/
why does this work? Well my understanding ist that I loaded
the file into the embedded ruby, after that T1 is known, so I can look
it up. The problem I now is why rb_load_file does not work the same
way */
obj = rb_cv_get(klass, “@@some_var”);

for (i = 0; i < RARRAY(obj)->len; ++i){
printf(“obj[%d] = %s\n”, i, STR2CSTR(rb_ary_entry(obj,i)));
}
return 0;
}

Comments are welcome!

Anyway thanks for your answer.

Regards
Friedrich

int main (void){
  int i;
  VALUE obj;
  VALUE klass;
  ruby_init(); /* embed Ruby into this program! */

    /* At this step you are playing a dangerous game with the GC */

  /* uby_script("embed");
     rb_load_file("t1.rb"); */
  obj = rb_eval_string("load 't1.rb'");

     ruby_init_loadpath(); /* initialize search path */
     rb_require("t1"); /* no need for eval */

        /* question why does rb_load_file does not work? */
  klass = rb_const_get(rb_cObject, rb_intern("T1"));
        /* why does this work? Well my understanding ist that I loaded
the file into the embedded ruby, after that T1 is known, so I can look
it up. The problem I now is why rb_load_file does not work the same
way */

    /* test if @@some_var is defined before trying to access it */

  obj = rb_cv_get(klass, "@@some_var");

    /* test here if obj is really an Array */
  

  for (i = 0; i < RARRAY(obj)->len; ++i){
    printf("obj[%d] = %s\n", i, STR2CSTR(rb_ary_entry(obj,i)));
  }
  return 0;
}

If ruby give an error, you'll have a segfault : none of your calls are
protected.

Guy Decoux

Hi,

rb_cvar_get() or rb_cv_get(). The former accepts ID and name
for the latter.
Well it’s a bit different (as I found out myself short after my
posting)

Just illustrated how to use those functions. I didn’t know that
you wanted to make ruby embedded, because you didn’t write so.

ruby_init(); /* embed Ruby into this program! /
/
uby_script(“embed”);
rb_load_file(“t1.rb”); /
obj = rb_eval_string(“load ‘t1.rb’”);
/
question why does rb_load_file does not work? */

HOW doesn’t it work? Possibly, you need to call ruby_init_loadpath().

···

At Fri, 28 Feb 2003 20:23:14 +0900, Friedrich Dominicus wrote:


Nobu Nakada

ts decoux@moulon.inra.fr writes:

int main (void){
int i;
VALUE obj;
VALUE klass;
ruby_init(); /* embed Ruby into this program! */

/* At this step you are playing a dangerous game with the GC */

what you you mean which this step ?
ruby_init? How should I know what else to set up or use?

/* uby_script(“embed”);
rb_load_file(“t1.rb”); */
obj = rb_eval_string(“load ‘t1.rb’”);

 ruby_init_loadpath(); /* initialize search path */
 rb_require("t1");     /* no need for eval */
    /* question why does rb_load_file does not work? */

klass = rb_const_get(rb_cObject, rb_intern(“T1”));
/* why does this work? Well my understanding ist that I loaded
the file into the embedded ruby, after that T1 is known, so I can look
it up. The problem I now is why rb_load_file does not work the same
way */

/* test if @@some_var is defined before trying to access it */

obj = rb_cv_get(klass, “@@some_var”);

/* test here if obj is really an Array */

for (i = 0; i < RARRAY(obj)->len; ++i){
printf(“obj[%d] = %s\n”, i, STR2CSTR(rb_ary_entry(obj,i)));
}
return 0;
}

If ruby give an error, you’ll have a segfault : none of your calls are
protected.
Thanks I’ll rewrite my stuff. I just wonder how you learned the usage,
as told before I have searched a lot if messages, but did not found
something that shows this…

Regards
Friedrich

As said I rewrote it a bit it now looks like this (no error handling!)

/* Generated header

  • File Name : t1.c
···
  • Created : 2003-02-28 09:57:47 frido
  • Author : Friedrich Dominicus
  • Time-stamp: <>
    */

#include <ruby.h>
#include <stdio.h>

int main (void){
int i;
VALUE obj;
VALUE klass;
ruby_init();
ruby_init_loadpath();
/* uby_script(“embed”);
rb_load_file(“t1.rb”); */
//obj = rb_eval_string(“load ‘t1.rb’”);
rb_require(“t1”);
klass = rb_const_get(rb_cObject, rb_intern(“T1”));
obj = rb_cv_get(klass, “@@some_var”);

for (i = 0; i < RARRAY(obj)->len; ++i){
printf(“obj[%d] = %s\n”, i, STR2CSTR(rb_ary_entry(obj,i)));
}
return 0;
}

This works and gives:

obj[0] = String1
obj[1] = String2
obj[2] = String3

But now the very same program under Windows (just modified to call
NtInitialize before somethint else crashes after rb_const_get

this is the source I want to use under Windows:

#include <ruby.h>
#include <stdio.h>

int main (int argc, char**argv){
int i;
VALUE obj;
VALUE klass;
NtInitialize(&argc, &argv);
ruby_init();
ruby_init_loadpath();
rb_require(“t1”);
klass = rb_const_get(rb_cObject, rb_intern(“T1”));
obj = rb_cv_get(klass, “@@some_var”);

for (i = 0; i < RARRAY(obj)->len; ++i){
printf(“obj[%d] = %s\n”, i, STR2CSTR(rb_ary_entry(obj,i)));
}
return 0;
}

I can not see why it works on Linux but crashes on Windows

It really would be helpful is someone has something that simple
working and could give me hand.

Regards
Friedrich

ts <decoux@moulon.inra.fr> writes:

int main (void){
int i;
VALUE obj;
VALUE klass;
ruby_init(); /* embed Ruby into this program! */

/* At this step you are playing a dangerous game with the GC */

what you you mean which this step ?
ruby_init? How should I know what else to set up or use?

Here a stupid example :

   int main(void)
   {
       char i;
       VALUE obj;
       VALUE klass;

       ruby_init();
       obj = rb_str_new2("a string");

       /* call some ruby functions which call the GC */

       i = RSTRING(obj)->ptr[0];

       /* there are many chances than the String referenced by obj
          was removed by the GC, and you have a segfault when you try
          to access RSTRING(obj)->ptr[0] */

       return 0;
   }

Thanks I'll rewrite my stuff. I just wonder how you learned the usage,
as told before I have searched a lot if messages, but did not found
something that shows this...

You have also rb_load_protect() if you want to load a file and catch the
errors

    rb_load_protect(VALUE path, int wrap, int *state);

if wrap is not null, ruby make the load in an anonymous module
If ruby has an error, state will be not null.

Guy Decoux

Thanks I’ll rewrite my stuff. I just wonder how you learned the usage,

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/65628

:wink:

as told before I have searched a lot if messages, but did not found
something that shows this…

Interfacing with Ruby is easy when you hold the whole implementation in
your head :slight_smile:

···

On Fri, Feb 28, 2003 at 11:23:38PM +0900, Friedrich Dominicus wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Actually, typing random strings in the Finder does the equivalent of
filename completion.
– Discussion on file completion vs. the Mac Finder

But now the very same program under Windows (just modified to call
NtInitialize before somethint else crashes after rb_const_get

Well, I know nothing about Windows but I think that you must define
IMPORT and NT (if it run under NT) when you compile it

Something like /D "IMPORT" /D NT=1

Guy Decoux

ts decoux@moulon.inra.fr writes:

ts decoux@moulon.inra.fr writes:

int main (void){
int i;
VALUE obj;
VALUE klass;
ruby_init(); /* embed Ruby into this program! */

/* At this step you are playing a dangerous game with the GC */
what you you mean which this step ?
ruby_init? How should I know what else to set up or use?

Here a stupid example :

int main(void)
{
char i;
VALUE obj;
VALUE klass;

   ruby_init();
   obj = rb_str_new2("a string");

   /* call some ruby functions which call the GC */

   i = RSTRING(obj)->ptr[0];

   /* there are many chances than the String referenced by obj
      was removed by the GC, and you have a segfault when you try
      to access RSTRING(obj)->ptr[0] */

Ok I understand that now, what do I have to do that it does not
happen?

What’s the simplest but too safe way to solve my simple problem. I
just want the C side access the Ruby side as partly pointed out here.

You have also rb_load_protect() if you want to load a file and catch the
errors

rb_load_protect(VALUE path, int wrap, int *state);

Ok, thanks I’ll try it with the Windows progrm.

Regards
Friedrich

Mauricio Fernández batsman.geo@yahoo.com writes:

Thanks I’ll rewrite my stuff. I just wonder how you learned the usage,

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/65628

:wink:
Well as I understand the docs are on Japanese. Well ahem my Japanese
is non-exitant."

as told before I have searched a lot if messages, but did not found
something that shows this…

Interfacing with Ruby is easy when you hold the whole implementation in
your head :slight_smile:
Well, probably my head is to small? Therefor I need some examples from
the parts I’m able to keep in it.:wink:

Regards
Friedrich

···

On Fri, Feb 28, 2003 at 11:23:38PM +0900, Friedrich Dominicus wrote:

ts decoux@moulon.inra.fr writes:

But now the very same program under Windows (just modified to call
NtInitialize before somethint else crashes after rb_const_get

Well, I know nothing about Windows but I think that you must define
IMPORT and NT (if it run under NT) when you compile it

Something like /D “IMPORT” /D NT=1
Well I have used NT but not IMPORT, will try tomorrow.

Regards
Friedrich

ts decoux@moulon.inra.fr writes:

But now the very same program under Windows (just modified to call
NtInitialize before somethint else crashes after rb_const_get

Well, I know nothing about Windows but I think that you must define
IMPORT and NT (if it run under NT) when you compile it

Something like /D “IMPORT” /D NT=1
Well it seems I was missing the IMPORT define, with it it now give the
expected output.

Thanks for your help
Friedrich

Ok I understand that now, what do I have to do that it does not
happen?

Well in my case you need to write

   void tt()
   {
       char i;
       VALUE obj;

       obj = rb_str_new2("a string");

       /* call some ruby functions which call the GC */

       i = RSTRING(obj)->ptr[0];
   }

   int main(void)
   {
       ruby_init();
       ruby_init_loadpath();
       tt();
       return 0;
   }

Now the GC will see `obj' on the stack and will mark the string.

The problem with my example

   int main(void)
   {
       char i;
       VALUE obj;
       VALUE klass;

       ruby_init();
       obj = rb_str_new2("a string");
       /* etc */

   }

is that ruby can't see that `klass' and `obj' are on the stack and it will
not be marked by the GC.

Guy Decoux

Wrap your code inside a function (with the variables declared inside)
and call it after doing ruby_init().

Explanation (probably inaccurate):

Ruby’s GC is conservative, meaning that it will look for references to
objects in C’s stack. However, the base of the stack is found when you
call ruby_init, so if there were values in a deeper stack-frame they will
be ignored.

The sequence of (pertinent) functions called is
ruby_init
Init_heap
Init_stack → gets the start of C’s stack by taking the address of an
argument and saves it for later GC runs

then at some point when marking the GC does
rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END);

that’s why it will only mark objects held in stack frames over (less
deep than) the initial one (the one ruby_init was run in).

···

On Sat, Mar 01, 2003 at 12:04:03AM +0900, Friedrich Dominicus wrote:

   /* there are many chances than the String referenced by obj
      was removed by the GC, and you have a segfault when you try
      to access RSTRING(obj)->ptr[0] */

Ok I understand that now, what do I have to do that it does not
happen?

What’s the simplest but too safe way to solve my simple problem. I
just want the C side access the Ruby side as partly pointed out here.


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

This is a scsi driver, scraes the shit out of me, therefore I tapdanced
and wrote a unix clone around it (C) by linus
– Somewhere in the kernel tree

Thanks I’ll rewrite my stuff. I just wonder how you learned the usage,

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/65628

:wink:
Well as I understand the docs are on Japanese. Well ahem my Japanese
is non-exitant."

The point is that for most of us the sources are the only documentation when
something isn’t mentioned in the Pickaxe. BUT Guy Decoux doesn’t need docs.

as told before I have searched a lot if messages, but did not found
something that shows this…

Interfacing with Ruby is easy when you hold the whole implementation in
your head :slight_smile:
Well, probably my head is to small? Therefor I need some examples from
the parts I’m able to keep in it.:wink:

This makes me think of matz’s talk at LL2

“we, mere mortals, are limited”
(shows horizontal line over brain-power graph)

“some even less”
(lowers the line => laughters)

What happens here is that you were asking “I wonder how you learned the
usage” to one of the persons who knows the most about Ruby’s internals
(I have the feeling he could recite the source code :).

WE are the mere mortals, HE is the Ruby-hacker god.

···

On Sat, Mar 01, 2003 at 02:05:01AM +0900, Friedrich Dominicus wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Why are there always boycotts? Shouldn’t there be girlcotts too?
– argon on #Linux

void do_stuff()
{
char i;
VALUE obj;
VALUE klass;

obj = rb_str_new2("a string");

/* call some ruby functions which call the GC */

i = RSTRING(obj)->ptr[0];
...

}

int main(void)
{
ruby_init();
do_stuff();
}

···

On Fri, Oct 10, 2003 at 01:15:26AM +0900, Friedrich Dominicus wrote:

/* At this step you are playing a dangerous game with the GC */
what you you mean which this step ?
ruby_init? How should I know what else to set up or use?

Here a stupid example :

int main(void)
{
char i;
VALUE obj;
VALUE klass;

   ruby_init();
   obj = rb_str_new2("a string");

   /* call some ruby functions which call the GC */

   i = RSTRING(obj)->ptr[0];

   /* there are many chances than the String referenced by obj
      was removed by the GC, and you have a segfault when you try
      to access RSTRING(obj)->ptr[0] */

Ok I understand that now, what do I have to do that it does not
happen?

What’s the simplest but too safe way to solve my simple problem. I
just want the C side access the Ruby side as partly pointed out here.


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

We apologize for the inconvenience, but we’d still like yout to test out
this kernel.
– Linus Torvalds, announcing another kernel patch

isn’t there some effort at a wiki-rdoc hackup of the ruby source? if so,
could someone point me to it? if not, let’s start it.

-a

···

On Sat, 1 Mar 2003, Mauricio [iso-8859-1] Fernández wrote:

The point is that for most of us the sources are the only documentation when
something isn’t mentioned in the Pickaxe. BUT Guy Decoux doesn’t need docs.

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

ts decoux@moulon.inra.fr writes:

Ok I understand that now, what do I have to do that it does not
happen?

Well in my case you need to write

void tt()
{
char i;
VALUE obj;

   obj = rb_str_new2("a string");

   /* call some ruby functions which call the GC */

   i = RSTRING(obj)->ptr[0];

}
I have another question related to this, aren’t there any functions
provided to inform the GC that a particular object should not be
collected at the moment? As shown I do not know the ins/outs from
Ruby, but I have learned about dealing with a copying GC in Eiffel an
there some features are provided to exclude a particular object from
beein moved. There this function have names with freeze or frozen in
it. Is OBJ_FREEZE supposed to do something simular?

Regards
Friedrich