RubyのMemoryView入門(5)
前
要素数を176000で固定してハードコードしているから動的な、というのはちょっと変だけど、ファイルから読み込むことで予め値が分からないという意味で動的。
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);
const int n_samples = 176000;
FILE *fp = fopen(audio_path, "rb");
if (fp == NULL) {
rb_raise(rb_eRuntimeError, "failed to open file");
}
fseek(fp, 0, SEEK_SET);
const unsigned long read_size = fread(samples, sizeof(short), n_samples, fp);
if (read_size != n_samples) {
fclose(fp);
rb_raise(rb_eRuntimeError, "failed to read file");
}
fclose(fp);
view->obj = obj;
view->data = samples;
view->byte_size = sizeof(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);
}
code:test/test_learning_memory_view.rb
require "test/unit"
require "fiddle"
require "learning_memory_view"
require "tempfile"
class TestLearningMemoryView < Test::Unit::TestCase
include LearningMemoryView
class TestShortArray < self
def test_short_array
size = 176000
Tempfile.create do |tempfile|
tempfile.write Array.new(size, 3).pack("s*")
short_array = ShortArray.new(tempfile.path)
Fiddle::MemoryView.export short_array do |memory_view|
assert_equal 2, memory_view.item_size
assert_equal 2 * size, memory_view.byte_size
assert_equal "s", memory_view.format
rb_unpacked = File.read(tempfile.to_path).unpack("s*")
assert_equal size, rb_unpacked.length
mv_unpacked = memory_view.to_s.unpack("#{memory_view.format}*")
assert_equal size, mv_unpacked.length
diffs = []
rb_unpacked.zip(mv_unpacked).each_with_index do |(a, b), i|
diffs << i if a != b
end
end
assert_equal [].length, diffs.length
end
end
end
end
end
が、これはうまく行かない。
テストするとこんな感じにのエラーになってしまう:
code:shell
% rake test
Loaded suite /Users/kitaitimakoto/.gem/ruby/3.3.6/gems/rake-13.2.1/lib/rake/rake_test_loader
Started
found 175020: 3 != -31376
found 175021: 3 != 28066
found 175022: 3 != 1
found 175023: 3 != 0
found 175024: 3 != 27044
found 175025: 3 != 698
found 175026: 3 != 1
found 175027: 3 != 0
found 175032: 3 != 150
found 175033: 3 != -15122
found 175034: 3 != -29510
F
=====================================================================================================================================================================================================
Failure: test_short_array(TestLearningMemoryView::TestShortArray)
/Users/kitaitimakoto/src/gitlab.com/KitaitiMakoto/learning-memory-view/test/test_learning_memory_view.rb:54:in `block (2 levels) in test_short_array'
51: diffs0..10.each do |i| 53: end
=> 54: assert_equal [].length, diffs.length
55: end
56: end
57: end
/Users/kitaitimakoto/src/gitlab.com/KitaitiMakoto/learning-memory-view/test/test_learning_memory_view.rb:38:in `export'
/Users/kitaitimakoto/src/gitlab.com/KitaitiMakoto/learning-memory-view/test/test_learning_memory_view.rb:38:in `block in test_short_array'
/Users/kitaitimakoto/.gem/ruby/3.3.6/gems/tempfile-0.3.1/lib/tempfile.rb:576:in `create_with_filename'
/Users/kitaitimakoto/.gem/ruby/3.3.6/gems/tempfile-0.3.1/lib/tempfile.rb:562:in `create'
/Users/kitaitimakoto/src/gitlab.com/KitaitiMakoto/learning-memory-view/test/test_learning_memory_view.rb:34:in `test_short_array'
<0> expected but was
<965>
=====================================================================================================================================================================================================
Finished in 0.045941 seconds.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4 tests, 12 assertions, 1 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
75% passed
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
87.07 tests/s, 261.20 assertions/s
rake aborted!
Command failed with status (1)
/Users/kitaitimakoto/.gem/ruby/3.3.6/gems/rake-13.2.1/exe/rake:27:in `<top (required)>'
Tasks: TOP => test
(See full trace by running task with --trace)
175020バイト目以降がおかしなことになってしまう。
十年以上プログラミングしてきたけど、どうやったらスタックオーバーフローになるか知らなくて初めて仕込んだ。
記録のため、この問題のある実装を載せておく。
分かったこと
ちゃんとAPIを整理する時まで、一旦置いておこう。
次