2012-09-03 55 views
4

我们在嵌入式ruby应用程序中观察到一种奇怪的行为。我们已经精简了代码,并且能够重新产生问题。以下是详细信息。嵌入式ruby的奇怪行为

1. Ruby代码

#!/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” 文件的源代码,我们得到以下错误

未定义的方法`loopF unc'为主体:对象
NoMethodError

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

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

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

+0

这是一个如何提出明确SO问题的范例。 –

回答

1

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