今日は、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件のフィードバック
コメントは受け付けていません。