diff --git a/ext/fiddle/memory_view.c b/ext/fiddle/memory_view.c index 05eb883b..4139ab08 100644 --- a/ext/fiddle/memory_view.c +++ b/ext/fiddle/memory_view.c @@ -103,21 +103,25 @@ rb_fiddle_memview_s_available_p(VALUE klass, VALUE target) } static VALUE -rb_fiddle_memview_s_export(VALUE klass, VALUE target) +rb_fiddle_memview_s_export(int argc, VALUE *argv, VALUE klass) { ID id_new; CONST_ID(id_new, "new"); - VALUE memview = rb_funcall(klass, id_new, 1, target); + VALUE memview = rb_funcallv(klass, id_new, argc, argv); return rb_ensure(rb_yield, memview, rb_fiddle_memview_release, memview); } static VALUE -rb_fiddle_memview_initialize(VALUE obj, VALUE target) +rb_fiddle_memview_initialize(int argc, VALUE *argv, VALUE obj) { + VALUE target, flags_v; + rb_scan_args(argc, argv, "11", &target, &flags_v); + int flags = NIL_P(flags_v) ? 0 : NUM2INT(flags_v); + struct memview_data *data; TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - if (!rb_memory_view_get(target, &data->view, 0)) { + if (!rb_memory_view_get(target, &data->view, flags)) { data->view.obj = Qnil; rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target); } @@ -314,9 +318,18 @@ Init_fiddle_memory_view(void) { rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject); rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate); + rb_define_const(rb_cMemoryView, "SIMPLE", INT2NUM(RUBY_MEMORY_VIEW_SIMPLE)); + rb_define_const(rb_cMemoryView, "WRITABLE", INT2NUM(RUBY_MEMORY_VIEW_WRITABLE)); + rb_define_const(rb_cMemoryView, "FORMAT", INT2NUM(RUBY_MEMORY_VIEW_FORMAT)); + rb_define_const(rb_cMemoryView, "MULTI_DIMENSIONAL", INT2NUM(RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL)); + rb_define_const(rb_cMemoryView, "STRIDES", INT2NUM(RUBY_MEMORY_VIEW_STRIDES)); + rb_define_const(rb_cMemoryView, "ROW_MAJOR", INT2NUM(RUBY_MEMORY_VIEW_ROW_MAJOR)); + rb_define_const(rb_cMemoryView, "COLUMN_MAJOR", INT2NUM(RUBY_MEMORY_VIEW_COLUMN_MAJOR)); + rb_define_const(rb_cMemoryView, "ANY_CONTIGUOUS", INT2NUM(RUBY_MEMORY_VIEW_ANY_CONTIGUOUS)); + rb_define_const(rb_cMemoryView, "INDIRECT", INT2NUM(RUBY_MEMORY_VIEW_INDIRECT)); rb_define_singleton_method(rb_cMemoryView, "available?", rb_fiddle_memview_s_available_p, 1); - rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, 1); - rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1); + rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, -1); + rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, -1); rb_define_method(rb_cMemoryView, "release", rb_fiddle_memview_release, 0); rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0); rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0); diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c index 9eddd717..87abc864 100644 --- a/ext/fiddle/pointer.c +++ b/ext/fiddle/pointer.c @@ -137,6 +137,8 @@ fiddle_ptr_memory_view_available_p(VALUE obj) static bool fiddle_ptr_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags) { + if (flags != RUBY_MEMORY_VIEW_SIMPLE) return false; + struct ptr_data *data = fiddle_ptr_check_memory_view(obj); rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, true); diff --git a/test/fiddle/test_memory_view.rb b/test/fiddle/test_memory_view.rb index c141daf9..fa2e6840 100644 --- a/test/fiddle/test_memory_view.rb +++ b/test/fiddle/test_memory_view.rb @@ -36,6 +36,31 @@ def test_available? assert {!MemoryView.available?(Object.new)} end + def test_new_with_flags + ptr = Pointer["hello world"] + mview = MemoryView.new(ptr, MemoryView::SIMPLE) + begin + assert_equal(ptr.size, mview.byte_size) + ensure + mview.release + end + end + + def test_new_with_unsupported_flags + ptr = Pointer["hello world"] + assert_raise(ArgumentError) do + MemoryView.new(ptr, MemoryView::WRITABLE) + end + end + + def test_export_with_flags + str = "hello world" + mview_str = MemoryView.export(Pointer[str], MemoryView::SIMPLE) do |mview| + mview.to_s + end + assert_equal(str, mview_str) + end + def test_memory_view_from_pointer str = Marshal.load(Marshal.dump("hello world")) ptr = Pointer[str]