Skip to content

Commit 8dc7c05

Browse files
authored
Support flags in Fiddle::MemoryView.new and .export (#209)
Accept an optional `flags` argument, expose the flag values as constants, and reject unsupported flags in `Fiddle::Pointer`'s provider.
1 parent 1c54c9b commit 8dc7c05

3 files changed

Lines changed: 46 additions & 6 deletions

File tree

‎ext/fiddle/memory_view.c‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,21 +103,25 @@ rb_fiddle_memview_s_available_p(VALUE klass, VALUE target)
103103
}
104104

105105
static VALUE
106-
rb_fiddle_memview_s_export(VALUE klass, VALUE target)
106+
rb_fiddle_memview_s_export(int argc, VALUE *argv, VALUE klass)
107107
{
108108
ID id_new;
109109
CONST_ID(id_new, "new");
110-
VALUE memview = rb_funcall(klass, id_new, 1, target);
110+
VALUE memview = rb_funcallv(klass, id_new, argc, argv);
111111
return rb_ensure(rb_yield, memview, rb_fiddle_memview_release, memview);
112112
}
113113

114114
static VALUE
115-
rb_fiddle_memview_initialize(VALUE obj, VALUE target)
115+
rb_fiddle_memview_initialize(int argc, VALUE *argv, VALUE obj)
116116
{
117+
VALUE target, flags_v;
118+
rb_scan_args(argc, argv, "11", &target, &flags_v);
119+
int flags = NIL_P(flags_v) ? 0 : NUM2INT(flags_v);
120+
117121
struct memview_data *data;
118122
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
119123

120-
if (!rb_memory_view_get(target, &data->view, 0)) {
124+
if (!rb_memory_view_get(target, &data->view, flags)) {
121125
data->view.obj = Qnil;
122126
rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target);
123127
}
@@ -314,9 +318,18 @@ Init_fiddle_memory_view(void)
314318
{
315319
rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject);
316320
rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate);
321+
rb_define_const(rb_cMemoryView, "SIMPLE", INT2NUM(RUBY_MEMORY_VIEW_SIMPLE));
322+
rb_define_const(rb_cMemoryView, "WRITABLE", INT2NUM(RUBY_MEMORY_VIEW_WRITABLE));
323+
rb_define_const(rb_cMemoryView, "FORMAT", INT2NUM(RUBY_MEMORY_VIEW_FORMAT));
324+
rb_define_const(rb_cMemoryView, "MULTI_DIMENSIONAL", INT2NUM(RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL));
325+
rb_define_const(rb_cMemoryView, "STRIDES", INT2NUM(RUBY_MEMORY_VIEW_STRIDES));
326+
rb_define_const(rb_cMemoryView, "ROW_MAJOR", INT2NUM(RUBY_MEMORY_VIEW_ROW_MAJOR));
327+
rb_define_const(rb_cMemoryView, "COLUMN_MAJOR", INT2NUM(RUBY_MEMORY_VIEW_COLUMN_MAJOR));
328+
rb_define_const(rb_cMemoryView, "ANY_CONTIGUOUS", INT2NUM(RUBY_MEMORY_VIEW_ANY_CONTIGUOUS));
329+
rb_define_const(rb_cMemoryView, "INDIRECT", INT2NUM(RUBY_MEMORY_VIEW_INDIRECT));
317330
rb_define_singleton_method(rb_cMemoryView, "available?", rb_fiddle_memview_s_available_p, 1);
318-
rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, 1);
319-
rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
331+
rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, -1);
332+
rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, -1);
320333
rb_define_method(rb_cMemoryView, "release", rb_fiddle_memview_release, 0);
321334
rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0);
322335
rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0);

‎ext/fiddle/pointer.c‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ fiddle_ptr_memory_view_available_p(VALUE obj)
137137
static bool
138138
fiddle_ptr_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
139139
{
140+
if (flags != RUBY_MEMORY_VIEW_SIMPLE) return false;
141+
140142
struct ptr_data *data = fiddle_ptr_check_memory_view(obj);
141143
rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, true);
142144

‎test/fiddle/test_memory_view.rb‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,31 @@ def test_available?
3636
assert {!MemoryView.available?(Object.new)}
3737
end
3838

39+
def test_new_with_flags
40+
ptr = Pointer["hello world"]
41+
mview = MemoryView.new(ptr, MemoryView::SIMPLE)
42+
begin
43+
assert_equal(ptr.size, mview.byte_size)
44+
ensure
45+
mview.release
46+
end
47+
end
48+
49+
def test_new_with_unsupported_flags
50+
ptr = Pointer["hello world"]
51+
assert_raise(ArgumentError) do
52+
MemoryView.new(ptr, MemoryView::WRITABLE)
53+
end
54+
end
55+
56+
def test_export_with_flags
57+
str = "hello world"
58+
mview_str = MemoryView.export(Pointer[str], MemoryView::SIMPLE) do |mview|
59+
mview.to_s
60+
end
61+
assert_equal(str, mview_str)
62+
end
63+
3964
def test_memory_view_from_pointer
4065
str = Marshal.load(Marshal.dump("hello world"))
4166
ptr = Pointer[str]

0 commit comments

Comments
 (0)