Pregunta

He estado usando Python durante mucho tiempo y acabo de comenzar a jugar con Ruby, pero estoy encontrando las diferencias entre los módulos en los dos idiomas realmente confusos, especialmente cuando se ve a través de sus C-API. Por ejemplo, aquí hay un pequeño módulo 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));
}

Cuando importo y llamo eso como así

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

Esperaba que funcionara de manera similar a cómo funcionarían los módulos de Python. Sin embargo, estoy descubriendo que tengo que usar PyModule para extender una clase o debo usar include "PyModule". Estoy buscando una manera de tener PyModule Adjunte estas funciones al objeto del módulo similar a la semántica de Python. También tengo curiosidad por saber qué está sucediendo realmente en Ruby que le da este comportamiento.

¿Fue útil?

Solución

El módulo puede ser útil como espacios de nombres, tanto en Ruby como en Python, pero los módulos en Ruby son diferentes en que también sirven como mezclas.

Tu confusión es entre instancia Métodos (como los que está definiendo y que se importan al incluir un módulo) y único Métodos (como los que está tratando de llamar y que no se importan en la inclusión).

Puedes usar rb_define_singleton_method en vez de rb_define_method Y obtendrás el efecto que quieres. Sin embargo, en ese caso, su módulo no tendrá ningún método de instancia, por lo que incluirlo o extenderlo no tendrá ningún efecto.

Personalmente prefiero definir los métodos como métodos de instancia y extender el módulo consigo mismo Entonces los métodos están disponibles en ambos sentidos. En C, puedes usar rb_extend_object(PyModule, PyModule); Para hacer eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top