I'm writing an app that calls ruby code from c. I am having a little difficulty and wondered if anyone could point me in the rite direction.
I currently have in my C.
#include ruby.hmain(){ ruby_init(); rb_require("myRubyFile"); rb_funcall(rb_module_new(), rb_intern("RubyFunction"), 0, NULL);}My ruby file is in the same directory as my c file and is called myRubyFile.rb and contains a definition of the function RubyFunction().
This is a cut down of what I actually want to do, just making it more readable for others. I just require some feedback as to whether this is the correct method to call ruby code from my c file.
Regards
- Quick suggestions: 1) don't omit ruby_init_loadpath() (I SEGV without this), 2) don't name the method
RubyFunction-- when called without parens ruby will look for aconstant of the same name, and, 3) you probably want a "static" method defined in an application-specific class or module, not one def'd against the implicitself(see answer).pilcrow– pilcrow2010-05-11 15:32:23 +00:00CommentedMay 11, 2010 at 15:32
3 Answers3
Short answer:
extern VALUE rb_vm_top_self(void); /* Assumes 1.9. Under 1.8, use the global * VALUE ruby_top_self */...rb_funcall(rb_vm_top_self(), /* irb> RubyFunction() */ rb_intern("RubyFunction"), /* irb> self.RubyFunction() # same thing */ 0, NULL);Longer answer:
The first argument torb_funcall is thereceiver of the method call.
Assuming youdefinedRubyFunction() outside of any explicit class or module context, then it is added to the eigenclass of the implicit,main object at the "top level" of every ruby vm.
In ruby, this object is accessible as the top-levelself:
$ cat myRubyFile.rb# file: myRubyFile.rbdef foo puts "foo"end$ irbirb> require "myRubyFile"=> trueirb> foofoo=> nilirb> self.foo() # same thing, more explicitfoo=> nilirb> self=> mainIn C under 1.9 it is accessible as indicated above.
Comments
I try to use the following approach:
Basic struct to share data
typedef struct ruby_shared_data { VALUE obj; ID method_id; int nargs; VALUE args[4];} ruby_shared_data;Create a function for call ruby objects on some part of your code
static VALUE ruby_callback(VALUE ptr) { ruby_shared_data *data = (ruby_shared_data*)ptr; return rb_funcall2(data->obj,data->method_id,data->nargs,data->args);}On some part of your code...
ruby_shared_data rbdata; rbdata.obj = obj; rbdata.method_id = rb_intern("mycallback"); rbdata.nargs = 1; rbdata.args[0] = rb_str_new2("im a parameter"); int error = 0; VALUE result = rb_protect(ruby_callback,(VALUE)&rbdata,&error); if (error) throw "Ruby exception on callback";Is always a good idea to wrap rb_funcall with rb_protect.
Another interesting thing is to know the parameters of the callback, one approach is the following
ruby_shared_data rbdata;rbdata.obj = callback;rbdata.method_id = rb_intern("arity"); rbdata.nargs = 0;int error = 0;VALUE result = rb_protect(ruby_callback,(VALUE)&rbdata,&error);if (error) throw "Ruby exception on callback";narguments = NUM2INT(result);Comments
I don't like to call ruby from inside C unless you have complex C project which you don't want to re-build in ruby.
There are two ways to interact between C and ruby. You can extend ruby with code written in C. SeeSWIG.
Or you can embed ruby, seehere,here andhere.
BTW, what do you mention is "embed" ruby, not "extend" ruby.
Comments
Explore related questions
See similar questions with these tags.


