Lua上でmrubyを動かすための禁断のLuaライブラリを作った

今日は、6キロのランニングを達成できたご褒美に、突発一人ハッカソンをやりました。眠たかったので、すぐできそうだけど、禁断とされている(勝手な思い)Lua上でmrubyを動かすためのLuaライブラリ(mruby-on-Lua)を作りました。

Lua上でmrubyを動かすためのLuaライブラリ

以下のLuaライブラリを作りました。こんな感じでとても簡単にできます。

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

#include "mruby.h"
#include "mruby/proc.h"
#include "mruby/compile.h"

static int l_mruby_code(lua_State *L)
{
    int ret, n;
    mrb_state *mrb;
    struct mrb_parser_state* p;
    const char *mrb_code;

    mrb = mrb_open();

    mrb_code = lua_tostring(L, 1);

    p = mrb_parse_string(mrb, mrb_code);
    n = mrb_generate_code(mrb, p->tree);

    mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_nil_value());

    ret =  n > 0 ? 0 : 1;
    lua_pushnumber(L, ret);

    mrb_close(mrb);

    return 1;
}

static int l_mruby_file(lua_State *L)
{
    int ret, n;
    mrb_state *mrb;
    FILE *mrb_file;
    struct mrb_parser_state* p;
    const char *mruby_code_file;

    mrb = mrb_open();

    mruby_code_file = lua_tostring(L, 1);

    if ((mrb_file = fopen(mruby_code_file, "r")) == NULL)
        return -1;

    p = mrb_parse_file(mrb, mrb_file);
    n = mrb_generate_code(mrb, p->tree);

    mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_nil_value());

    ret =  n > 0 ? 0 : 1;
    lua_pushnumber(L, ret);

    mrb_close(mrb);

    return 1;
}

static const struct luaL_reg mrubylib[] = {
    {"run_file", l_mruby_file},
    {"run", l_mruby_code},
    {NULL, NULL},
};

int luaopen_mruby(lua_State *L)
{
    luaL_register (L, "mruby", mrubylib);
    return 1;
}

実際に動かしてみた

まずはGithubからソースをとってきてコンパイルします。Makefile内のLuaやmrubyのライブラリパスを自分の環境に合わせて変更しmakeして下さい。
テストのmrubyスクリプト(./test.mrb)はシンプルに以下の通り。

puts "mruby file run on Lua!!"

mrubyをLua上で動かすためのLuaスクリプトサンプル(sample.lua)は以下の通り。mrubyスクリプトファイルや、直接mrubyのコードをLuaの中にかいても実行できます。

require "mruby"

file = "./test.mrb"

print(">> mruby file run ./test.mrb")
mruby.run_file(file)

print(">> mruby code run")
mruby.run("puts 'mruby code run on Lua!!'")

lua sample.luaで実行してみると、以下の出力が得られたら成功です。

>> mruby file run ./test.mrb
mruby file run on Lua!!
>> mruby code run
mruby code run on Lua!!

うーむ、禁断である。

もう少し禁断なコードに挑戦(2012/06/03 追記)

以下のように書いちゃうと、もはやLuaである必要がありませんね。Luaがかわいそうになってしまいます。以下のコードは一応、「Lua」のコードですのでお間違えないように。(勘違いされないように補足しておきますが、Luaもmrubyも好きですよ!)

require "mruby"

mruby.run([[

def tak(x, y, z)

    if y >= x
        z
    else
        tak(tak(x - 1, y, z),tak(y - 1, z, x),tak(z - 1, x, y))
    end
end

print tak(20, 12, 7)

]])

禁断すぎる。

意外と使えるかも?

Luaで組み込んでいる場合に、このライブラリを加えるだけで、簡単にmrubyをLuaに組み込んで使えるので意外と気軽に使えるかもしれませんね。是非お試しを。

「Lua上でmrubyを動かすための禁断のLuaライブラリを作った」への2件のフィードバック

コメントは受け付けていません。