mruby/初期化を読む
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[mrubyを読む]]
#contents
*はじめに [#o2d08338]
初期化の際に呼び出されるのはmrb_open()関数のようです。
* mrb_open(src/state.c) [#y0e781ad]
それでは早速mrb_open()を見てみましょう。
#code(C){{
mrb_state*
mrb_open()
{
mrb_state *mrb = mrb_open_allocf(allocf);
return mrb;
}
}}
というわけでmrb_open_allocf()に委譲です。
*allocf(src/state.c) [#vd2aeb9f]
mrb_open_allocf()に進む前にallocfとは何者なのか見てみまし...
#code(C){{
static void*
allocf(mrb_state *mrb, void *p, size_t size)
{
if (size == 0) {
free(p);
return NULL;
}
else {
return realloc(p, size);
}
}
}}
というわけでallocfとはメモリ確保・解放関数のようです。mru...
allocfに書いてあることをそのまま書くとallocf、というかmrb...
-第2引数で指定されているメモリ領域を第3引数で指定した量に...
-第3引数が0の場合は第2引数が指すメモリ領域を開放する
2つ目の仕様がなんか気にくわないですがallocfの呼び出しをwr...
src/gc.c
#code(C){{
void*
mrb_realloc(mrb_state *mrb, void *p, size_t len)
{
return (mrb->allocf)(mrb, p, len);
}
void*
mrb_malloc(mrb_state *mrb, size_t len)
{
return (mrb->allocf)(mrb, 0, len);
}
void*
mrb_calloc(mrb_state *mrb, size_t nelem, size_t len)
{
void *p = (mrb->allocf)(mrb, 0, nelem*len);
memset(p, 0, nelem*len);
return p;
}
void*
mrb_free(mrb_state *mrb, void *p)
{
return (mrb->allocf)(mrb, p, 0);
}
}}
ちなみに、freeが別関数になっていないのは気持ち悪いとか0サ...
*mrb_open_allocf(src/state.c) [#r6a38647]
さて、話が長くなりましたがmrb_open_allocf()です。
#code(C){{
mrb_state*
mrb_open_allocf(mrb_allocf f)
{
mrb_state *mrb = (f)(NULL, NULL, sizeof(mrb_state));
memset(mrb, 0, sizeof(mrb_state));
mrb->allocf = f;
mrb->current_white_part = MRB_GC_WHITE_A;
mrb_init_heap(mrb);
mrb_init_core(mrb);
mrb_init_ext(mrb);
return mrb;
}
}}
見ての通り、mrb_state構造体を確保した後、ヒープやコアライ...
mrb_init_heap()は普通にヒープを初期化しているだけなので飛...
*mrb_init_core(src/init.c) [#x374ac89]
mrb_init_core()ですが予想通りにRubyオブジェクトスペースの...
#code(C){{
void
mrb_init_core(mrb_state *mrb)
{
mrb_init_symtbl(mrb);
mrb_init_class(mrb);
mrb_init_object(mrb);
mrb_init_kernel(mrb);
mrb_init_comparable(mrb);
mrb_init_enumerable(mrb);
mrb_init_symbols(mrb);
mrb_init_proc(mrb);
mrb_init_string(mrb);
mrb_init_array(mrb);
mrb_init_hash(mrb);
mrb_init_numeric(mrb);
mrb_init_range(mrb);
mrb_init_struct(mrb);
mrb_init_gc(mrb);
#ifdef INCLUDE_REGEXP
mrb_init_regexp(mrb);
mrb_init_encoding(mrb);
#endif
mrb_init_exception(mrb);
mrb_init_print(mrb);
mrb_init_time(mrb);
mrb_init_math(mrb);
mrb_init_mrblib(mrb);
mrb_gc_arena_restore(mrb, 0);
}
}}
RegexpとEncodingの構築は条件コンパイルになっています。正...
さて、各initに進みます。まず初めのmrb_init_symtbl()は予想...
**mrb_init_class(src/class.c) [#jb38f539]
次にmrb_init_class()を見てみます。BasicObject, Object, Mo...
#code(C){{
/* boot class hierarchy */
bob = boot_defclass(mrb, 0);
obj = boot_defclass(mrb, bob); mrb->object_class = obj;
mod = boot_defclass(mrb, obj); mrb->module_class = mod;...
cls = boot_defclass(mrb, mod); mrb->class_class = cls; ...
/* fix-up loose ends */
bob->c = obj->c = mod->c = cls->c = cls;
make_metaclass(mrb, bob);
make_metaclass(mrb, obj);
make_metaclass(mrb, mod);
make_metaclass(mrb, cls);
/* name basic classes */
mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value...
mrb_define_const(mrb, obj, "Object", mrb_obj_value(obj));
mrb_define_const(mrb, obj, "Module", mrb_obj_value(mod));
mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls));
/* name each classes */
mrb_name_class(mrb, bob, mrb_intern(mrb, "BasicObject"));
mrb_name_class(mrb, obj, mrb_intern(mrb, "Object"));
mrb_name_class(mrb, mod, mrb_intern(mrb, "Module"));
mrb_name_class(mrb, cls, mrb_intern(mrb, "Class"));
}}
mrb_define_class()とmrb_define_class()から呼ばれる関数は...
#code(C){{
struct RClass*
mrb_define_class(mrb_state *mrb, const char *name, struct...
{
struct RClass *c;
c = mrb_define_class_id(mrb, mrb_intern(mrb, name), sup...
return c;
}
struct RClass*
mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct ...
{
struct RClass *c = mrb_class_new(mrb, super);
mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class,
name, mrb_obj_value(c));
mrb_name_class(mrb, c, name);
return c;
}
struct RClass *
mrb_class_new(mrb_state *mrb, struct RClass *super)
{
struct RClass *c;
if (super) {
mrb_check_inheritable(mrb, super);
}
c = boot_defclass(mrb, super);
make_metaclass(mrb, c);
return c;
}
static void
make_metaclass(mrb_state *mrb, struct RClass *c)
{
struct RClass *sc;
if (c->c->tt == MRB_TT_SCLASS) {
return;
}
sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, ...
sc->mt = 0;
if (!c->super) {
sc->super = mrb->class_class;
}
else {
sc->super = c->super->c;
}
c->c = sc;
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct...
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struc...
}
}}
さて、というわけでBasicObject, Object, Module, Classがmrb...
-クラス名をobject_classに登録しようにもobject_classがまだ...
-メタクラスを設定しようにもclass_classがまだ生成されてい...
というわけです。
**mrb_define_method(src/class.c) [#s39ce6fb]
さて、クラスを定義したので次はメソッドです。メソッドを定...
#code(C){{
mrb_define_method(mrb, bob, "initialize", mrb_bob_init,...
mrb_define_method(mrb, bob, "!", mrb_bob_not, ARGS_NONE...
mrb_define_method(mrb, bob, "method_missing", mrb_bob_m...
mrb_define_method(mrb, cls, "new", mrb_instance_new, AR...
mrb_define_method(mrb, cls, "inherited", mrb_bob_init, ...
mrb_define_method(mrb, mod, "include", mrb_mod_include,...
}}
大体、CRubyと同じです。最後の引数だけやや違う。ARGS_*の定...
#code(C){{
/* required arguments */
#define ARGS_REQ(n) (((n)&0x1f) << 19)
/* optional arguments */
#define ARGS_OPT(n) (((n)&0x1f) << 14)
/* rest argument */
#define ARGS_REST() (1 << 13)
/* required arguments after rest */
#define ARGS_POST(n) (((n)&0x1f) << 8)
/* keyword arguments (n of keys, kdict) */
#define ARGS_KEY(n1,n2) ((((n1)&0x1f) << 3) | ((n2)?(1<<2...
/* block argument */
#define ARGS_BLOCK() (1 << 1)
/* accept any number of arguments */
#define ARGS_ANY() ARGS_REST()
/* accept no arguments */
#define ARGS_NONE() 0
}}
というわけで引数の種類を示すビット情報になっているようで...
では、mrb_define_method()に進みます。
#code(C){{
void
mrb_define_method(mrb_state *mrb, struct RClass *c, const...
{
mrb_define_method_id(mrb, c, mrb_intern(mrb, name), fun...
}
void
mrb_define_method_id(mrb_state *mrb, struct RClass *c, mr...
{
struct RProc *p;
p = mrb_proc_new_cfunc(mrb, func);
p->target_class = c;
mrb_define_method_raw(mrb, c, mid, p);
}
}}
というわけで、mrubyではメソッドはProcにラップされるようで...
最後に、登録されている関数をいくつか見てみましょう。
#code(C){{
static mrb_value
mrb_bob_not(mrb_state *mrb, mrb_value cv)
{
...
}
static mrb_value
mrb_mod_include(mrb_state *mrb, mrb_value klass)
{
...
}
mrb_value
mrb_instance_new(mrb_state *mrb, mrb_value cv)
{
...
}
}}
わかることとしては、引数の数によらず登録する関数は
mrb_stateとmrb_valueを受け取り、mrb_valueを返す
という形式であるということです。関数の呼び出される仕組み...
**mrb_define_class_method(src/class.c) [#cc1383af]
クラスメソッドの定義についても説明しておきましょう。
#code(C){{
void
mrb_define_class_method(mrb_state *mrb, struct RClass *c,...
{
mrb_define_method_id(mrb, c->c, mrb_intern(mrb, name), ...
}
}}
c->cとはなんでしょうか?答えは上の方にありますがメタクラ...
**mrb_init_mrblib(mrblib/init_mrblib.c) [#bc54e143]
後はまったり読み流せばいいやと思いきやまた面白いコードが...
src/compar.c
#code(C){{
void
mrb_init_comparable(mrb_state *mrb)
{
mrb_define_module(mrb, "Comparable");
}
}}
なんとComparableはモジュールだけ定義されていてメソッドが...
どういうカラクリかというと実はmrubyのビルドプロセスは2つ...
:ステップ1|コア部分のビルド
:ステップ2|Rubyで書かれたコードをコンパイルしてライブラリ...
ということをしています。ステップ2のカラクリを担当している...
#code(C){{
extern const char mrblib_irep[];
void
mrb_init_mrblib(mrb_state *mrb)
{
int n = mrb_read_irep(mrb, mrblib_irep);
extern mrb_value mrb_top_self(mrb_state *mrb);
mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_s...
}
}}
実行系はまだ読んでいませんがなんとなく、「コンパイルしたR...
*mrb_init_ext(src/init_ext.c) [#r8d82d69]
さて初期化の最後にmrb_init_ext()を見てみましょう。
#code(C){{
void
mrb_init_ext(mrb_state *mrb)
{
#ifdef INCLUDE_SOCKET
extern void mrb_init_socket(mrb_state *mrb);
mrb_init_socket(mrb);
#endif
}
}}
CRubyでは拡張ライブラリを動的ロードする仕組みがありますが...
*mrb_state(include/mruby.h) [#x42e3db3]
今まで特に取り上げずに進めてきましたが、mrubyのオブジェク...
*おわりに [#l800cbc6]
というわけでmrubyの初期化、mrb_open()から始まる世界を見て...
-CRubyの知識はmruby読解の役に立つ
-いろいろと組み込み向けと思われるケアがある
といったところでしょうか。
終了行:
[[mrubyを読む]]
#contents
*はじめに [#o2d08338]
初期化の際に呼び出されるのはmrb_open()関数のようです。
* mrb_open(src/state.c) [#y0e781ad]
それでは早速mrb_open()を見てみましょう。
#code(C){{
mrb_state*
mrb_open()
{
mrb_state *mrb = mrb_open_allocf(allocf);
return mrb;
}
}}
というわけでmrb_open_allocf()に委譲です。
*allocf(src/state.c) [#vd2aeb9f]
mrb_open_allocf()に進む前にallocfとは何者なのか見てみまし...
#code(C){{
static void*
allocf(mrb_state *mrb, void *p, size_t size)
{
if (size == 0) {
free(p);
return NULL;
}
else {
return realloc(p, size);
}
}
}}
というわけでallocfとはメモリ確保・解放関数のようです。mru...
allocfに書いてあることをそのまま書くとallocf、というかmrb...
-第2引数で指定されているメモリ領域を第3引数で指定した量に...
-第3引数が0の場合は第2引数が指すメモリ領域を開放する
2つ目の仕様がなんか気にくわないですがallocfの呼び出しをwr...
src/gc.c
#code(C){{
void*
mrb_realloc(mrb_state *mrb, void *p, size_t len)
{
return (mrb->allocf)(mrb, p, len);
}
void*
mrb_malloc(mrb_state *mrb, size_t len)
{
return (mrb->allocf)(mrb, 0, len);
}
void*
mrb_calloc(mrb_state *mrb, size_t nelem, size_t len)
{
void *p = (mrb->allocf)(mrb, 0, nelem*len);
memset(p, 0, nelem*len);
return p;
}
void*
mrb_free(mrb_state *mrb, void *p)
{
return (mrb->allocf)(mrb, p, 0);
}
}}
ちなみに、freeが別関数になっていないのは気持ち悪いとか0サ...
*mrb_open_allocf(src/state.c) [#r6a38647]
さて、話が長くなりましたがmrb_open_allocf()です。
#code(C){{
mrb_state*
mrb_open_allocf(mrb_allocf f)
{
mrb_state *mrb = (f)(NULL, NULL, sizeof(mrb_state));
memset(mrb, 0, sizeof(mrb_state));
mrb->allocf = f;
mrb->current_white_part = MRB_GC_WHITE_A;
mrb_init_heap(mrb);
mrb_init_core(mrb);
mrb_init_ext(mrb);
return mrb;
}
}}
見ての通り、mrb_state構造体を確保した後、ヒープやコアライ...
mrb_init_heap()は普通にヒープを初期化しているだけなので飛...
*mrb_init_core(src/init.c) [#x374ac89]
mrb_init_core()ですが予想通りにRubyオブジェクトスペースの...
#code(C){{
void
mrb_init_core(mrb_state *mrb)
{
mrb_init_symtbl(mrb);
mrb_init_class(mrb);
mrb_init_object(mrb);
mrb_init_kernel(mrb);
mrb_init_comparable(mrb);
mrb_init_enumerable(mrb);
mrb_init_symbols(mrb);
mrb_init_proc(mrb);
mrb_init_string(mrb);
mrb_init_array(mrb);
mrb_init_hash(mrb);
mrb_init_numeric(mrb);
mrb_init_range(mrb);
mrb_init_struct(mrb);
mrb_init_gc(mrb);
#ifdef INCLUDE_REGEXP
mrb_init_regexp(mrb);
mrb_init_encoding(mrb);
#endif
mrb_init_exception(mrb);
mrb_init_print(mrb);
mrb_init_time(mrb);
mrb_init_math(mrb);
mrb_init_mrblib(mrb);
mrb_gc_arena_restore(mrb, 0);
}
}}
RegexpとEncodingの構築は条件コンパイルになっています。正...
さて、各initに進みます。まず初めのmrb_init_symtbl()は予想...
**mrb_init_class(src/class.c) [#jb38f539]
次にmrb_init_class()を見てみます。BasicObject, Object, Mo...
#code(C){{
/* boot class hierarchy */
bob = boot_defclass(mrb, 0);
obj = boot_defclass(mrb, bob); mrb->object_class = obj;
mod = boot_defclass(mrb, obj); mrb->module_class = mod;...
cls = boot_defclass(mrb, mod); mrb->class_class = cls; ...
/* fix-up loose ends */
bob->c = obj->c = mod->c = cls->c = cls;
make_metaclass(mrb, bob);
make_metaclass(mrb, obj);
make_metaclass(mrb, mod);
make_metaclass(mrb, cls);
/* name basic classes */
mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value...
mrb_define_const(mrb, obj, "Object", mrb_obj_value(obj));
mrb_define_const(mrb, obj, "Module", mrb_obj_value(mod));
mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls));
/* name each classes */
mrb_name_class(mrb, bob, mrb_intern(mrb, "BasicObject"));
mrb_name_class(mrb, obj, mrb_intern(mrb, "Object"));
mrb_name_class(mrb, mod, mrb_intern(mrb, "Module"));
mrb_name_class(mrb, cls, mrb_intern(mrb, "Class"));
}}
mrb_define_class()とmrb_define_class()から呼ばれる関数は...
#code(C){{
struct RClass*
mrb_define_class(mrb_state *mrb, const char *name, struct...
{
struct RClass *c;
c = mrb_define_class_id(mrb, mrb_intern(mrb, name), sup...
return c;
}
struct RClass*
mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct ...
{
struct RClass *c = mrb_class_new(mrb, super);
mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class,
name, mrb_obj_value(c));
mrb_name_class(mrb, c, name);
return c;
}
struct RClass *
mrb_class_new(mrb_state *mrb, struct RClass *super)
{
struct RClass *c;
if (super) {
mrb_check_inheritable(mrb, super);
}
c = boot_defclass(mrb, super);
make_metaclass(mrb, c);
return c;
}
static void
make_metaclass(mrb_state *mrb, struct RClass *c)
{
struct RClass *sc;
if (c->c->tt == MRB_TT_SCLASS) {
return;
}
sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, ...
sc->mt = 0;
if (!c->super) {
sc->super = mrb->class_class;
}
else {
sc->super = c->super->c;
}
c->c = sc;
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct...
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struc...
}
}}
さて、というわけでBasicObject, Object, Module, Classがmrb...
-クラス名をobject_classに登録しようにもobject_classがまだ...
-メタクラスを設定しようにもclass_classがまだ生成されてい...
というわけです。
**mrb_define_method(src/class.c) [#s39ce6fb]
さて、クラスを定義したので次はメソッドです。メソッドを定...
#code(C){{
mrb_define_method(mrb, bob, "initialize", mrb_bob_init,...
mrb_define_method(mrb, bob, "!", mrb_bob_not, ARGS_NONE...
mrb_define_method(mrb, bob, "method_missing", mrb_bob_m...
mrb_define_method(mrb, cls, "new", mrb_instance_new, AR...
mrb_define_method(mrb, cls, "inherited", mrb_bob_init, ...
mrb_define_method(mrb, mod, "include", mrb_mod_include,...
}}
大体、CRubyと同じです。最後の引数だけやや違う。ARGS_*の定...
#code(C){{
/* required arguments */
#define ARGS_REQ(n) (((n)&0x1f) << 19)
/* optional arguments */
#define ARGS_OPT(n) (((n)&0x1f) << 14)
/* rest argument */
#define ARGS_REST() (1 << 13)
/* required arguments after rest */
#define ARGS_POST(n) (((n)&0x1f) << 8)
/* keyword arguments (n of keys, kdict) */
#define ARGS_KEY(n1,n2) ((((n1)&0x1f) << 3) | ((n2)?(1<<2...
/* block argument */
#define ARGS_BLOCK() (1 << 1)
/* accept any number of arguments */
#define ARGS_ANY() ARGS_REST()
/* accept no arguments */
#define ARGS_NONE() 0
}}
というわけで引数の種類を示すビット情報になっているようで...
では、mrb_define_method()に進みます。
#code(C){{
void
mrb_define_method(mrb_state *mrb, struct RClass *c, const...
{
mrb_define_method_id(mrb, c, mrb_intern(mrb, name), fun...
}
void
mrb_define_method_id(mrb_state *mrb, struct RClass *c, mr...
{
struct RProc *p;
p = mrb_proc_new_cfunc(mrb, func);
p->target_class = c;
mrb_define_method_raw(mrb, c, mid, p);
}
}}
というわけで、mrubyではメソッドはProcにラップされるようで...
最後に、登録されている関数をいくつか見てみましょう。
#code(C){{
static mrb_value
mrb_bob_not(mrb_state *mrb, mrb_value cv)
{
...
}
static mrb_value
mrb_mod_include(mrb_state *mrb, mrb_value klass)
{
...
}
mrb_value
mrb_instance_new(mrb_state *mrb, mrb_value cv)
{
...
}
}}
わかることとしては、引数の数によらず登録する関数は
mrb_stateとmrb_valueを受け取り、mrb_valueを返す
という形式であるということです。関数の呼び出される仕組み...
**mrb_define_class_method(src/class.c) [#cc1383af]
クラスメソッドの定義についても説明しておきましょう。
#code(C){{
void
mrb_define_class_method(mrb_state *mrb, struct RClass *c,...
{
mrb_define_method_id(mrb, c->c, mrb_intern(mrb, name), ...
}
}}
c->cとはなんでしょうか?答えは上の方にありますがメタクラ...
**mrb_init_mrblib(mrblib/init_mrblib.c) [#bc54e143]
後はまったり読み流せばいいやと思いきやまた面白いコードが...
src/compar.c
#code(C){{
void
mrb_init_comparable(mrb_state *mrb)
{
mrb_define_module(mrb, "Comparable");
}
}}
なんとComparableはモジュールだけ定義されていてメソッドが...
どういうカラクリかというと実はmrubyのビルドプロセスは2つ...
:ステップ1|コア部分のビルド
:ステップ2|Rubyで書かれたコードをコンパイルしてライブラリ...
ということをしています。ステップ2のカラクリを担当している...
#code(C){{
extern const char mrblib_irep[];
void
mrb_init_mrblib(mrb_state *mrb)
{
int n = mrb_read_irep(mrb, mrblib_irep);
extern mrb_value mrb_top_self(mrb_state *mrb);
mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_s...
}
}}
実行系はまだ読んでいませんがなんとなく、「コンパイルしたR...
*mrb_init_ext(src/init_ext.c) [#r8d82d69]
さて初期化の最後にmrb_init_ext()を見てみましょう。
#code(C){{
void
mrb_init_ext(mrb_state *mrb)
{
#ifdef INCLUDE_SOCKET
extern void mrb_init_socket(mrb_state *mrb);
mrb_init_socket(mrb);
#endif
}
}}
CRubyでは拡張ライブラリを動的ロードする仕組みがありますが...
*mrb_state(include/mruby.h) [#x42e3db3]
今まで特に取り上げずに進めてきましたが、mrubyのオブジェク...
*おわりに [#l800cbc6]
というわけでmrubyの初期化、mrb_open()から始まる世界を見て...
-CRubyの知識はmruby読解の役に立つ
-いろいろと組み込み向けと思われるケアがある
といったところでしょうか。
ページ名: