4

We are observing a strange behavior on our embedded ruby application. We have stripped down the code to bare minimal and were able to re-produce the issue. Following are the details.

1. The ruby code

#!/usr/bin/env ruby
#require "MyLibrary.so"   *// Works fine*
module AA
  class BC
    def initialize
    end

    def loadFunction
      require "MyLibrary.so" *//Gives error*
    end
  end
end


#Invoke the method  
AA::BC.new().loadFunction            

2. Source code for MyLibrary.so

#include "ruby.h"

const char loop[] =  
   "def loopFunc\n"  
     "puts \"HERE\"\n"  
   "end\n"  

   "begin\n"  
     "loopFunc()\n"  
   "rescue StandardError\n"  
     "puts $!\n"  
     "puts $!.class\n"  
   "end\n";  

void initialize()  
{  
     ruby_init();  
     ruby_init_loadpath();  
     rb_eval_string(loop);  
}

extern "C" void Init_MyLibrary()  
{
    initialize();
}    

When we require "MyLibrary.so" file inside the loadFunction in rb file, we are getting following error

undefined method `loopFunc' for main:Object
NoMethodError

However when we require at top of the rb file everything works fine.

Our first guess was that rb_eval_string() gets executed inside the module AA. So loopFunc is getting defined inside the module AA instead of being global. Therefore NoMethodError is being reported. When we invoked AA::BC.new().loopFunc() inside the cpp file, the method gets invoked successfully; which confirmed our guess.

Is this the expected behavior from an embedded ruby point of view because if we require an rb file(instead of .so) with the same code as passed to rb_eval_string, we are not getting any error.

undur_gongor
  • 15,657
  • 5
  • 63
  • 75
sudeep dasan
  • 81
  • 1
  • 6

1 Answers1

1

rb_eval_string() does define the methods in the module from which it is invoked. We can either use rb_require/rb_load to get the correct behavior.

sudeep dasan
  • 81
  • 1
  • 6