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 M. ha scritto:

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

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

Shea M. 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

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.

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;

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

~S

rb_define_module_function(cls, “a_class_method”, _class_method, 2);

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

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

Shea M. 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:00, mercoledì 24 gennaio 2007, Shea M. ha scritto:

return 0;

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

Stefano C. wrote:

ruby_finalize();
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

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 M. ha scritto:

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

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

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.

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