4

我们在嵌入式 ruby​​ 应用程序上观察到一个奇怪的行为。我们已将代码精简到最低限度,并且能够重现该问题。以下是详细信息。

1.红宝石代码

#!/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. 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();
}    

当我们在 rb 文件的 loadFunction 中需要“MyLibrary.so”文件时,我们会收到以下错误


main:Object NoMethodError的未定义方法“loopFunc”

但是,当我们在 rb 文件顶部需要时,一切正常。

我们的第一个猜测是 rb_eval_string() 在模块 AA 中执行。所以 loopFunc 是在模块 AA 中定义的,而不是全局的。因此正在报告 NoMethodError。当我们在 cpp 文件中调用 AA::BC.new().loopFunc() 时,该方法被成功调用;这证实了我们的猜测。

从嵌入式 ruby​​ 的角度来看,这是预期的行为吗,因为如果我们需要一个 rb 文件(而不是 .so),其代码与传递给 rb_eval_string 的代码相同,我们不会收到任何错误。

4

1 回答 1

1

rb_eval_string() 确实定义了调用它的模块中的方法。我们可以使用 rb_require/rb_load 来获得正确的行为。

于 2012-09-04T13:35:43.287 回答