2012-09-03 89 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來獲得正確的行爲。