Семантика модуля Python против семантики модуля Ruby в их C-API - PullRequest
0 голосов
/ 16 февраля 2012

Я давно использую Python и только начал играть с Ruby, но я нахожу различия между модулями в двух языках действительно запутанными, особенно если смотреть через их C-API. Например, вот небольшой модуль ruby ​​C

#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, который дает ему такое поведение.

1 Ответ

3 голосов
/ 16 февраля 2012

Модуль может быть полезен в качестве пространства имен, как в Ruby, так и в Python, но модули в Ruby отличаются тем, что они также служат миксинами.

Ваша путаница возникает между экземплярами методами (например, теми, которые вы определяете и которые импортируются при включении модуля) и singleton методами (например, теми, которые вы пытаетесь вызвать и которые не импортируются при включении).

Вы можете использовать rb_define_singleton_method вместо rb_define_method, и вы получите желаемый эффект. В этом случае, однако, ваш модуль не будет иметь никаких методов экземпляра, поэтому его включение или расширение не будет иметь никакого эффекта.

Лично я предпочитаю определять методы как методы экземпляра и расширять модуль самим собой , чтобы методы были доступны обоими способами. В C вы можете использовать rb_extend_object(PyModule, PyModule); для этого.

...