RHGの逆襲で「st_tableを拡張で使うと便利だよ」という話を聞いて、へーと思ったので、st_tableで簡単なハッシュテーブルを実装してみた。
拡張ライブラリ
#ifdef _WIN32 __declspec(dllexport) void Init_my_hash(void); #endif #include "ruby.h" #include "st.h" static void my_hash_free(st_table *table) { st_free_table(table); } static VALUE my_hash_alloc(VALUE klass) { st_table *table = st_init_strtable(); return Data_Wrap_Struct(klass, 0, -1, table); } static VALUE my_hash_get(VALUE self, VALUE key) { st_table *table; st_data_t value = Qnil; Data_Get_Struct(self, st_table, table); Check_Type(key, T_STRING); st_lookup(table, (st_data_t) StringValuePtr(key), &value); return value; } static VALUE my_hash_set(VALUE self, VALUE key, VALUE value) { st_table *table; Data_Get_Struct(self, st_table, table); Check_Type(key, T_STRING); st_insert(table, (st_data_t) StringValuePtr(key), value); return Qnil; } void Init_my_hash() { VALUE MyHash; MyHash = rb_define_class("MyHash", rb_cObject); rb_define_alloc_func(MyHash, my_hash_alloc); rb_define_method(MyHash, "[]", my_hash_get, 1); rb_define_method(MyHash, "[]=", my_hash_set, 2); }
テスト
require 'my_hash' h = MyHash.new h['foo'] = 'bar' h['zoo'] = :zoo p h['foo'] #=> "bar" p h['zoo'] #=> :zoo
拡張ライブラリ側でメモリの開放をしたいときには便利かも。
てゆーか、Ruby以外でも使えそうだなー。