2012-02-15 67 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