Question

I've been using Python for a long time and I've just started to toy around with Ruby, but I'm finding the differences between modules in the two languages really confusing, especially when viewed through their C-APIs. For example, here is a small ruby C module

#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));
}

When I import and call that like so

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

I expected it to work similar to how python's modules would work. However, I am finding that I have to either use PyModule to extend a class or I must use include "PyModule". I'm looking for a way to have PyModule attach these functions to the module object similar to Python's semantics. I'm also curious what is actually happening in Ruby that gives it this behavior.

Was it helpful?

Solution

Module can be useful as namespaces, in both Ruby and Python, but modules in Ruby are different in that they serve as mixins too.

Your confusion is between instance methods (like those that you are defining and that are imported when including a Module) and singleton methods (like those that you are trying to call and that are not imported on inclusion).

You can use rb_define_singleton_method instead of rb_define_method and you will get the effect you want. In that case, though, your module will not have any instance methods, so including it or extending it won't have any effect.

I personally prefer to define the methods as instance methods and extend the module with itself so the methods are available in both ways. In C, you can use rb_extend_object(PyModule, PyModule); to do that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top