Ebedded: calling a C function from script

I have my embedded interpreter running my scipt. Now I would like my script to call function in my C++ program.

i.e.,

int getSomeValue()
{
   return 5;
}

void setSomeValue( int value )
{
   _value = value;
}

How would I call these functions from my ruby script?

~S

Alle 16:35, lunedì 22 gennaio 2007, Shea Martin ha scritto:

I have my embedded interpreter running my scipt. Now I would like my
script to call function in my C++ program.

i.e.,

int getSomeValue()
{
   return 5;
}

void setSomeValue( int value )
{
   _value = value;
}

How would I call these functions from my ruby script?

~S

If I understand correctly what you mean, I think you need to create a ruby
method wrapping that function. If you want to do that at kernel-level, that
is not inside a class, you should do the following (in your C code) (NOTE:
all this is untested. I've tried a little project which mixed ruby and C some
time ago, but soon abandoned it. What I'm telling comes from my memory of
that attempt and its source code):

1: define a static C function which wraps your own. It must accept at least
one argument of type VALUE (the first one is self) and return a VALUE (return
Qnil if you don't need the return value). For instance, a wrapper around your
getSomeValue() could be something like

static VALUE _getSomeValue(VALUE self){
  //INT2NUM converts from a C int to a ruby number (FixNum or BigNum)
  return INT2NUM(getSomeValue());
}

2: Create a ruby method which calls _getSomeValue. To do this, use the
rb_define_global_function function:

rb_define_global_function("get_some_value", _getSomeValue, 1);

Here the first argument is the name of the ruby method, _getSomeValue is a
pointer to the C function which implements the method and 1 is the number of
arguments of the C function.

After calling rb_define_global_function, you'll be able to
call "get_some_value" from your script:

puts get_some_value
=> 5

If you need more information on this topic, you can refer to the Pickaxe book,
in the chapter called (at least in the online edition) "Extending ruby".
Besides, you may find useful the ruby C api
(http://www.ruby-doc.org/doxygen/current/\) and, of course, ruby source code.
Moreover, today on the mailing list was announced a tutorial on writing ruby
extensions. It's at http://nanoblog.ath.cx/index.rb?module=readmore&id=8 I
haven't read it, so I don't know if it can be useful to you (there are
differences between writing an extension and embedding the interpreter)

I hope this helps

Stefano

Here is another one i can't find in the book or online:

How do I call a global function (which resides in a script) from C.

<script>
def script_main( args )
  puts "something"
end
</script>

<cpp>
ruby_init();
ruby_script("embedded");

init_my_ruby_stuff();

rb_load_file( "test.rb" )
ID id = rb_intern( "script_main" );
rb_funcall( rb_cObject, id, 0 );

ruby_finalize();

return 0;
<cpp/>

But this crashes with an access violation when I run it... am I doing something wrong?

~S

Thanks, that worked great. How do I do I define a class method? Doesn't seem to be in ruby book.
~S

Alle 17:00, mercoledì 24 gennaio 2007, Shea Martin ha scritto:

Here is another one i can't find in the book or online:

How do I call a global function (which resides in a script) from C.

<script>
def script_main( args )
  puts "something"
end
</script>

<cpp>
ruby_init();
ruby_script("embedded");

init_my_ruby_stuff();

rb_load_file( "test.rb" )
ID id = rb_intern( "script_main" );
rb_funcall( rb_cObject, id, 0 );

ruby_finalize();

return 0;
<cpp/>

But this crashes with an access violation when I run it... am I doing
something wrong?

~S

Your problem is that you're calling 'script_main', which is an instance method
of class object, as if it were a class method of Object. To do this, you
should access the top level object. I've tried to find the correct method to
do this, in vain. The best suggestion is this

VALUE top_level=rb_eval_string("self");
rb_funcall(self, rb_intern("script_main"),0);

As I said, there should be a better way, but this should work.

Stefano

Shea Martin wrote:

Thanks, that worked great. How do I do I define a class method? Doesn't seem to be in ruby book.
~S

Also, I can't seem to figure out how to pass ARGV to my script. I tried setting the global AGV before running, but it gets reset when I start.

~S

Stefano Crocco wrote:

Alle 17:00, mercoledì 24 gennaio 2007, Shea Martin ha scritto:

Here is another one i can't find in the book or online:

How do I call a global function (which resides in a script) from C.

<script>
def script_main( args )
  puts "something"
end
</script>

<cpp>
ruby_init();
ruby_script("embedded");

init_my_ruby_stuff();

rb_load_file( "test.rb" )
ID id = rb_intern( "script_main" );
rb_funcall( rb_cObject, id, 0 );

ruby_finalize();

return 0;
<cpp/>

But this crashes with an access violation when I run it... am I doing
something wrong?

~S

Your problem is that you're calling 'script_main', which is an instance method of class object, as if it were a class method of Object. To do this, you should access the top level object. I've tried to find the correct method to do this, in vain. The best suggestion is this

VALUE top_level=rb_eval_string("self");
rb_funcall(self, rb_intern("script_main"),0);

As I said, there should be a better way, but this should work.

Stefano

I tried what you said:

  VALUE script_obj = rb_eval_string("self");
  ID script_main_id = rb_intern("script_main");
  rb_funcall( script_obj, script_main_id, 0 );

but it crashes with the access violation.

I also tried this:

  VALUE script_obj = rb_class_new_instance( 0, 0, rb_cObject );
  ID script_main_id = rb_intern("script_main");
  rb_funcall( script_obj, script_main_id, 0 );

and it has the same problem.

Any ideas?

~S

Alle 16:25, mercoledì 24 gennaio 2007, Shea Martin ha scritto:

Shea Martin wrote:
> Thanks, that worked great. How do I do I define a class method? Doesn't
> seem to be in ruby book.
> ~S

Also, I can't seem to figure out how to pass ARGV to my script. I tried
setting the global AGV before running, but it gets reset when I start.

~S

You should use the ruby_options C function.

To define a class method, you should first define a class. This is done using
the rb_define_class function. It takes two parameters, the name of the class
(as a char*) and the superclass (as a VALUE, not its name). For instance, if
you want to define the class MyClass, as a subclass of Object, you'd do:

rb_define_class("MyClass", rb_cObject);

rb_cObject is a C global variable of type VALUE which corresponds to the ruby
Object class. rb_define_class returns a VALUE corresponding to the new class.
With it, you can define both instance methods and class methods.

To define a class method you should use rb_define_module_function, while to
define an instance method, you'd use the rb_define_method function. They both
takes four arguments: the class or module (the value returned by
rb_define_class, for instance), the name of the method, a pointer to the C
function which implements the method and the number of arguments this C
function takes (including the self argument).

A complete example (again, untested):

static VALUE _class_method(VALUE self, VALUE arg){
//Do something here and return a VALUE or Qnil
}

static VALUE _instance_method(VALUE self){
//Do something else here and return a VALUE or Qnil
}

void InitMyClass(){
  VALUE cls=rb_define_class("MyClass", rb_cObject);
  rb_define_module_function(cls, "a_class_method", _class_method, 2);
  rb_define_method(cls, "an_instance_method", _instance_method, 1);
}

Stefano

Alle 17:15, giovedì 25 gennaio 2007, Shea Martin ha scritto:

I tried what you said:

    VALUE script\_obj = rb\_eval\_string\(&quot;self&quot;\);
    ID script\_main\_id = rb\_intern\(&quot;script\_main&quot;\);
    rb\_funcall\( script\_obj, script\_main\_id, 0 \);

but it crashes with the access violation.

According to one of your previous posts, you use rb_load_file to load a file,
of course thinking that that was the C function corresponding to the
ruby 'load' method. The problem is that this is not true. The C function
corresponding to 'load' is rb_load, which takes one VALUE (the name of the
file, as a ruby string) and one int (analogous to the second parameter of the
ruby load method). Of course you could use the function corresponding
to 'require', rb_require, which takes a char* argument with the name of the
file. So, you should replace the code

rb_load_file( "test.rb" )

with

rb_load(rb_str_new2("test.rb"),0);

or with

rb_require("test.rb");

I hope this solves your problem

Stefano

  rb_define_module_function(cls, "a_class_method", _class_method, 2);

Aahh, that was the one I was looking for.
~S

According to one of your previous posts, you use rb_load_file to load a file, of course thinking that that was the C function corresponding to the ruby 'load' method. The problem is that this is not true. The C function corresponding to 'load' is rb_load, which takes one VALUE (the name of the file, as a ruby string) and one int (analogous to the second parameter of the ruby load method). Of course you could use the function corresponding to 'require', rb_require, which takes a char* argument with the name of the file. So, you should replace the code

rb_load_file( "test.rb" )

with

rb_load(rb_str_new2("test.rb"),0);

or with

rb_require("test.rb");

I hope this solves your problem

Stefano

I had fixed the problem using rb_require. Would it be better to use rb_load? rb_load is not mentioned in the pick axe book... which again brings up the question of if anyone knows of a reference for the ruby embedded API.

Thanks,
~S

Alle 20:55, venerdì 26 gennaio 2007, Shea Martin ha scritto:

> According to one of your previous posts, you use rb_load_file to load a
> file, of course thinking that that was the C function corresponding to
> the ruby 'load' method. The problem is that this is not true. The C
> function corresponding to 'load' is rb_load, which takes one VALUE (the
> name of the file, as a ruby string) and one int (analogous to the second
> parameter of the ruby load method). Of course you could use the function
> corresponding to 'require', rb_require, which takes a char* argument with
> the name of the file. So, you should replace the code
>
> rb_load_file( "test.rb" )
>
> with
>
> rb_load(rb_str_new2("test.rb"),0);
>
> or with
>
> rb_require("test.rb");
>
> I hope this solves your problem
>
> Stefano

I had fixed the problem using rb_require. Would it be better to use
rb_load? rb_load is not mentioned in the pick axe book... which again
brings up the question of if anyone knows of a reference for the ruby
embedded API.

Thanks,
~S

I think (but I'm not sure) that the difference between the two is exactly the
difference between load and require in ruby. Regarding the reference, the
only one I know is at www.ruby-doc.org. It doesn't contain documentation,
though: it's only a list of functions, variables and the like. It can still
be useful, for example to find the name of the C function corresponding to a
ruby method or of the object corresponding to one of the classes in ruby.
Usually, functions / variables corresponding to ruby methods / classes have
names beginning with rb_.

Stefano