読者です 読者をやめる 読者になる 読者になる

平凡なエンジニアの独り言 はてなブログ出張所

ピアノをこよなく愛するエセRubyistが適当に書き綴ります

mrubyにクラスとメソッドを組み込んでみた(Windows 7)

mruby

mrubyを使うなら、Cで拡張も書いてみたいですよね。とりあえず、Cでクラスとメソッドを組み込む方法を以下の記事を参考にしながら書いてみました。

概要

上記の記事では、モジュールの登録になっているので、クラスの登録をmrubyのコードを読みながら実施してみることにしました。下記のHelloクラスと同等のクラスをCで書いて、mrubyに登録します。

class Hello
  def hello(num)
    (0...num).each do |i|
      p "Hello mruby World!"
    end
  end
end

Hello.new.hello(3)

ソースコード

ソースコードは以下の通りです。

#include <mruby.h>
#include <mruby/proc.h>
#include <mruby/compile.h>

//登録するメソッドの処理
static mrb_value hello_hellofunc(mrb_state *mrb, mrb_value self) {
	int i;
	mrb_int arg;
	// 引数をmrb_int型(int型)で取得する
	// 第2引数について詳しく知りたい場合は、
	// class.cのmrb_get_args関数のコメントを見ること
	mrb_get_args(mrb, "i", &arg);
	
	for (i = 0; i < arg; i++) {
		puts("Hello mruby World!");
	}
	
	return self;
}

int main() {
	int n;
	mrb_state* mrb;
	struct mrb_parser_state* st;
	struct RClass *helloclass;
	char* code = "require 'hello'; Hello.new.hello(3)";

	mrb = mrb_open();

	//クラスを定義する
	helloclass = mrb_define_class(mrb, "Hello", mrb->object_class);
	//メソッドを定義する
	mrb_define_method(mrb, helloclass, "hello", hello_hellofunc, ARGS_REQ(1));

	st = mrb_parse_string(mrb, code);
	n = mrb_generate_code(mrb, st->tree);
	mrb_pool_close(st->pool);
	mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_nil_value());
}

ビルドは以下の感じです。適宜、環境に合わせて読み替えてください。

gcc -I../mruby/include -I../mruby/src practice_mruby.c ../mruby/lib/libmruby.a -o practice.exe

実行結果は以下の通り。

Hello mruby World!
Hello mruby World!
Hello mruby World!

ポイント

  • mrb_state型重要
  • mrb_get_args関数で引数を取得
  • mrb_define_class関数でクラス宣言
  • mrb_define_method関数でメソッド宣言
  • mruby.hやclass.cを読めばかなりのことがわかる

感想

特に難しいことはなさそうです。環境や言語をまたぐと厄介なのは、いろいろな型の受け渡しなので、その辺はもう少し調べてみる必要がありそうです。

mrubyはまだ情報が少ないので、とっつきにくいところもあるかもしれませんが、使う分には簡単そうですね。