我们在嵌入式 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 的代码相同,我们不会收到任何错误。