programmer
programmer

Reputation: 602

Embed Ruby in C and exntend

I have a requirement where I need to embed Ruby code in C++ (I could achieve this) and extend some functionality. When I try to call (require) my extension module, the program fails.

I have pasted a jist of the code below:

main.cpp

#include <ruby.h>

static VALUE Sum(VALUE rb_self, VALUE rb_param1, VALUE rb_param2)
{
    double val1 = NUM2DBL(rb_param1);
    double val2 = NUM2DBL(rb_param2);
    return rb_float_new(val1+val2);
}

void Init_myMod()
{
    myMod = rb_define_module("myMod");
    rb_define_module_function(myMod, "Sum", Sum, 2);
}

int main()
{
 ... Init ruby method...

    rb_require("myRubyfile");
    Init_myMod(); // This is where I need to push my ruby extension.
    rb_funcall(rb_mKernel, rb_intern("helloworld"), 0 , NULL);
.... 
}

myRubyfile.rb

require "myMod"

def helloworld()
    puts "Hello world"
    #puts "Sum of.. " + myMod.sum(4, 5)
end

The problem is if I dont use require "myMod" the code works and prints "Hello World", but if I use require.., the code dumps.

This is my requirement where I need to embed the ruby script in C, and reuse some of the C methods in ruby (extension).

Can someone help me with this?

Upvotes: 1

Views: 397

Answers (2)

Max
Max

Reputation: 22325

You're getting a segfault because the Ruby VM segfaults when there is an uncaught exception. You need to use something like rb_rescue or rb_protect to wrap the code which could raise an exception.

require "myMod" is raising an exception because require is only used to load files. You don't need to require anything because you're creating the module directly in the VM's memory. So... why the error? Well, if you were to write your module in Ruby, you'd get a syntax error:

module myMod
  ...
end
# SyntaxError: class/module name must be CONSTANT

But when you use rb_define_module, rather than raise an exception, Ruby does a tricky thing: it creates the module but doesn't expose it to the Ruby code. In order to expose the module to Ruby, just make the name valid:

// .cpp
rb_define_module("MyMod");

and

# .rb
puts "Sum of.. " + MyMod.Sum(4, 5).to_s

Upvotes: 2

cokedude
cokedude

Reputation: 387

Something like this should work. Make a bat script to your ruby script file and change system to the appropriate system call. Not sure if system() works in Windows. I have run many bash scripts this way so I would assume you can do the same thing in Windows.

#include <stdio.h>
#include <stdlib.h>

int main()
{
    puts("Starting now:");
    system("/path_to_script/script_name");
    return 0;
}

Upvotes: -1

Related Questions