2012-02-15 68 views
0

我一直在使用Python很久,並且剛開始玩弄Ruby,但是我發現兩個模塊之間的差異語言真的很混亂,特別是通過C-API查看時。例如,這裏是一個小紅寶石C模塊中Python模塊語義與其C-API中的Ruby模塊語義

#include "Python.h" 
#include "ruby.h" 

VALUE PyModule = Qnil; 
void Init_pymodule(); 
VALUE method_Py_Initialize(); 
VALUE method_PyRun_SimpleString(); 

void Init_pymodule() { 
    PyModule = rb_define_module("PyModule"); 
    rb_define_method(PyModule, "Py_Initialize", method_Py_Initialize, 0); 
    rb_define_method(PyModule, "PyRun_SimpleString", method_PyRun_SimpleString, 1); 
} 

VALUE method_Py_Initialize(VALUE self) { 
    Py_Initialize(); 
    return Qnil; 
} 

VALUE method_PyRun_SimpleString(VALUE self, VALUE command) { 
    return INT2NUM(PyRun_SimpleString(RSTRING(command)->as.ary)); 
} 

當我導入和調用像這樣

require "pymodule" 
PyModule.Py_Initialize() 
PyModule.PyRun_SimpleString("print 'hellooo'") 

我希望它的工作方式與Python的模塊將如何工作。但是,我發現我必須使用PyModule來擴展課程,或者我必須使用include "PyModule"。我正在尋找一種方法讓PyModule將這些函數附加到模塊對象,類似於Python的語義。我也很好奇Ruby中實際發生了什麼,使其發生了這種行爲。

回答

3

模塊在Ruby和Python中都可以用作名稱空間,但Ruby中的模塊不同之處在於它們也可以作爲mixin使用。

你的困惑是之間的實例方法(比如那些正在定義和被包括模塊時,進口)和方法(像那些你想打電話的非進口包容) 。

你可以使用rb_define_singleton_method而不是rb_define_method,你會得到你想要的效果。但是,在這種情況下,你的模塊不會有任何實例方法,所以包含它或擴展它將不會有任何影響。

我個人比較喜歡將方法定義爲實例方法,並將模塊與其自身的一起擴展,以便兩種方法都可用。在C中,你可以使用rb_extend_object(PyModule, PyModule);來做到這一點。

+0

是的,這正是問題所在。 Ruby有一個有趣的元類模型,因爲你可以擴展自己的類。 – dcolish 2012-02-16 17:40:37