How to "require" a third party module in C code when trying to call ruby methods from C?

I have the following code here:



#include <ruby.h>

int main(int argc, char* argv[])
{
    /* construct the VM */
    ruby_init();

    /* Ruby goes here */

    int state;
    VALUE result;
    result = rb_eval_string_protect("require 'strscan'", &state);

    if (state)
    {
        /* handle exception */
        VALUE exception = rb_errinfo();
        rb_funcall(rb_mKernel, rb_intern("puts"), 1, exception); // Just print out the exception
    }

    /* destruct the VM */
    return ruby_cleanup(0);
}

and when I run this code, I get the following error:

cannot load such file -- strscan
eval:1:in 'Kernel#require': cannot load such file -- strscan (LoadError)
    from eval:1:in '<main>'

which obviously hints that the program can not find the library.

I compiled my code with these commands:

clang -I/home/oof/.rubies/ruby-master/include/ruby-3.4.0+0/x86_64-linux -I/home/oof/.rubies/ruby-master/include/ruby-3.4.0+0 -L/home/oof/.rubies/ruby-master/lib -lruby -lm oof.c -o binary

and then I also ran export LD_LIBRARY_PATH=/home/oof/.rubies/ruby-master/lib/ before running my code, since the program needs to find libruby.so to run.

I compiled ruby from source according to these instructions and installed that compiled version to /home/oof/.rubies/ruby-master/

How can I import strscan (or any third party ruby code) into C-ruby?

Upvotes: 1

Views: 75

Answers (2)

user513951
user513951

Reputation: 13715

You are only missing ruby_init_loadpath() after ruby_init().

#include <ruby.h>

int main(int argc, char* argv[])
{
    /* construct the VM */
    ruby_init();
    ruby_init_loadpath(); // <= ADD THIS HERE

    /* Ruby goes here */

    int state;
    VALUE result;
    result = rb_eval_string_protect("require 'strscan'", &state);

    if (state)
    {
        /* handle exception */
        VALUE exception = rb_errinfo();
        rb_funcall(rb_mKernel, rb_intern("puts"), 1, exception); // Just print out the exception
    }

    /* destruct the VM */
    return ruby_cleanup(0);
}

This runs with no errors using Ruby 3.1.2.

Upvotes: 0

Casper
Casper

Reputation: 34328

I think you need to require rubygems first in order to load any gems.
This seems to work:

#include <ruby.h>

int main() {
  ruby_init();
  ruby_init_loadpath();

  rb_require("rubygems");
  rb_require("strscan");

  // Run some test code
  VALUE result = 
    rb_eval_string("StringScanner.new('Hello World').scan(/\\w+/)");

  // Print the result using the Ruby "p" method
  rb_p(result);

  ruby_finalize();    
  return 0;
}

Output:

 "Hello"

Upvotes: 1

Related Questions