我们正在观察嵌入式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”文件时,我们收到以下错误
主要的未定义方法`loopFunc':对象
NoMethodError
然而,当我们要求在rb文件的顶部一切正常。
我们的第一个猜测是rb_eval_string()在模块AA中执行。所以loopFunc在模块AA中定义而不是全局。因此报告了NoMethodError。当我们在cpp文件中调用AA :: BC.new()。loopFunc()时,该方法被成功调用;这证实了我们的猜测。
这是从嵌入式ruby角度来看的预期行为,因为如果我们需要一个rb文件(而不是.so)与传递给rb_eval_string的代码相同,我们就不会收到任何错误。
答案 0 :(得分:1)
rb_eval_string()确实定义了调用它的模块中的方法。我们可以使用rb_require / rb_load来获得正确的行为。