4

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

pilcrow's user avatar
pilcrow
59.2k14 gold badges101 silver badges147 bronze badges
askedMay 10, 2010 at 8:41
Lloyd Powell's user avatar
1
  • Quick suggestions: 1) don't omit ruby_init_loadpath() (I SEGV without this), 2) don't name the methodRubyFunction -- 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).CommentedMay 11, 2010 at 15:32

3 Answers3

6

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=> main

In C under 1.9 it is accessible as indicated above.

answeredMay 11, 2010 at 15:29
pilcrow's user avatar
Sign up to request clarification or add additional context in comments.

Comments

0

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);
answeredAug 10, 2015 at 20:43
camp0's user avatar

Comments

-2

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.

answeredMay 10, 2010 at 9:43
Yousf's user avatar

Comments

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.