Семантика модуля Python против Ruby Module Semantics в их APIS
-
25-10-2019 - |
Вопрос
Я долгое время использовал 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, что дает ему такое поведение.
Решение
Модуль может быть полезен в качестве пространств имен, как в Ruby, так и в Python, но модули в Ruby отличаются тем, что они также служат микшинами.
Ваша путаница между пример методы (например, те, которые вы определяете и импортируются при включении модуля) и Синглтон Методы (как те, которые вы пытаетесь позвонить, и которые не импортируются при включении).
Вы можете использовать rb_define_singleton_method
вместо rb_define_method
И вы получите желаемый эффект. В этом случае, однако, ваш модуль не будет иметь никаких методов экземпляра, поэтому включение его или расширения его не окажет никакого эффекта.
Я лично предпочитаю определять методы как методы экземпляра и расширять модуль с самим собой Таким образом, методы доступны обоими способами. В C вы можете использовать rb_extend_object(PyModule, PyModule);
сделать это.