RubyのMemoryView入門(6)
前
code:ext/learning_memory_view/learning_memory_view.c.diff
// ...
+ short *samples = ALLOC_N(short, n_samples);
// ...
- view->byte_size = sizeof(samples);
+ view->byte_size = sizeof(short) * n_samples;
// ...
(配列のサイズがsizeof(samples)で取れなくなった理由が分かってない)
動いた!
今回やったのは、「配列をスタックに置くのではなくて、ヒープに領域を確保する」ということらしい。
ヒープにメモリーを確保したのなら解放する処理を書かねばならない。
と思ったのだけど、rb_memory_view_t.dataは自分で解放しなくてもいい?
MemoryView の解放処理を実行する
release_func 関数を提供するライブラリは、rb_memory_view_t 構造体を適切に後始末する責務を持ちます。具体的には、shape、strides、sub_offsets、private のために割り当てたメモリ領域の解放が必要になるでしょう ((const 修飾子がついているので解放時に適切にキャストしないと警告が出てしまいます。ご注意ください。))。item_descは rb_memory_view_release 関数が解放するので触らないでおきましょう。
とあるのだけど、dataメンバーについては何も言っていない。
rb_memory_view_releaseがやってくれるってことかしらね。
一応結果のコードを載せておく。
ついでにハードコードしていた配列のサイズを、ファイルサイズから動的に決めるようにした。
code:ext/learning_memory_view/learning_memory_view.c
VALUE cShortArray;
static VALUE
short_array_initialize(VALUE self, VALUE audio_path)
{
rb_iv_set(self, "audio_path", audio_path);
return Qnil;
}
static bool
short_array_get_memory_view(const VALUE obj, rb_memory_view_t *view, int flags)
{
VALUE rb_audio_path = rb_iv_get(obj, "audio_path");
const char *audio_path = StringValueCStr(rb_audio_path);
FILE *fp = fopen(audio_path, "rb");
if (fp == NULL) {
rb_raise(rb_eRuntimeError, "failed to open file");
}
fpos_t file_size = 0;
fseek(fp, 0, SEEK_END);
fgetpos(fp, &file_size);
const unsigned long n_samples = file_size / sizeof(short);
short *samples = ALLOC_N(short, n_samples);
fseek(fp, 0, SEEK_SET);
const unsigned long read_size = fread(samples, sizeof(short), n_samples, fp);
if (read_size != (unsigned long)n_samples) {
fclose(fp);
rb_raise(rb_eRuntimeError, "failed to read file");
}
fclose(fp);
view->obj = obj;
view->data = samples;
view->byte_size = sizeof(short) * n_samples;
view->readonly = true;
view->format = "s";
view->item_size = sizeof(short);
view->item_desc.components = NULL;
view->item_desc.length = 0;
view->ndim = 1;
view->shape = NULL;
view->sub_offsets = NULL;
view->private_data = NULL;
return true;
}
static bool
short_array_release_memory_view(const VALUE obj, rb_memory_view_t *view)
{
return true;
}
static bool
short_array_memory_view_available_p(const VALUE obj)
{
return true;
}
static const rb_memory_view_entry_t short_array_view_entry = {
short_array_get_memory_view,
short_array_release_memory_view,
short_array_memory_view_available_p
};
void
Init_learning_memory_view(void)
{
VALUE mod = rb_define_module("LearningMemoryView");
cShortArray = rb_define_class_under(mod, "ShortArray", rb_cObject);
rb_memory_view_register(cShortArray, &short_array_view_entry);
rb_define_method(cShortArray, "initialize", short_array_initialize, 1);
}
short_array_memory_view_available_pで、audio_pathの存在とかを調べないといけないはず。
開けるかもこのタイミングで調べてもいい?
short_array_memory_view_available_pの時には開く権限あったけどshort_array_get_memory_viewの時には排他制御されてしまって開けない、とかもありそうだけど。
まあそれはファイルの存在も同じか。
次