Skip to content

Make Fiddle::Pointer's MemoryView writable - #215

Merged
kou merged 8 commits into
ruby:masterfrom
KitaitiMakoto:ptr-mv-writable
Aug 23, 2026
Merged

Make Fiddle::Pointer's MemoryView writable#215
kou merged 8 commits into
ruby:masterfrom
KitaitiMakoto:ptr-mv-writable

Conversation

@KitaitiMakoto

Copy link
Copy Markdown
Contributor

Hello,

This pull request allows Fiddle::Pointer to export a writable MemoryView.

The presence of the Fiddle::Pointer#[]= method suggests it is possible. If I'm mistaken, please let me know.

Thank you.

@kou

kou commented Aug 22, 2026

Copy link
Copy Markdown
Member

Could you accept both of SIMPLE (read-only) and WRITABLE?

@KitaitiMakoto

Copy link
Copy Markdown
Contributor Author

Let me clarify what you say.

Do you mean adding a test case to accept SIMPLE flag? Or, making the MemoryView readonly when SIMPLE flag is specified?

@kou

kou commented Aug 22, 2026

Copy link
Copy Markdown
Member

The latter.

@KitaitiMakoto

Copy link
Copy Markdown
Contributor Author

Done!

Comment thread ext/fiddle/pointer.c Outdated
Comment on lines +140 to +144
if (flags != RUBY_MEMORY_VIEW_SIMPLE) return false;
bool writable_requested = flags & RUBY_MEMORY_VIEW_WRITABLE;
if (flags != RUBY_MEMORY_VIEW_SIMPLE && flags != RUBY_MEMORY_VIEW_WRITABLE) 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);
rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, !writable_requested);

@kou kou Aug 22, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this style for easy to understand?

diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c
index 87abc86..d9b3d1c 100644
--- a/ext/fiddle/pointer.c
+++ b/ext/fiddle/pointer.c
@@ -137,10 +137,17 @@ 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;
+    bool read_only = true;
+    if (flags == RUBY_MEMORY_VIEW_SIMPLE) {
+        read_only = true;
+    } else if (flags == RUBY_MEMORY_VIEW_WRITABLE) {
+        read_only = false;
+    } else {
+        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);
+    rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, read_only);
 
     return true;
 }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a variable named read_only seems good.

However, I think checking whether the flags are supported and determining whether the MemoryView should be read-only are different concerns.

For instance, in the future, this function might accept other flags such as FORMAT and XXX_CONTIGUOUS (which include STRIDES). At that time, the function will check the bits of unsupported flag INDIRECT and return if they're on. It will look like:

if ((flags & RUBY_MEMORY_VIEW_INDIRECT) == RUBY_MEMORY_VIEW_INDIRECT) return false;

On the other hand, only the WRITABLE flag will affect read_only even the flags is combined with other flags:

// Even if `flags` is `RUBY_MEMORY_VIEW_WRITABLE | RUBY_MEMORY_VIEW_ROW_MAJOR`
bool read_only = !(flags & RUBY_MEMORY_VIEW_WRITABLE);

So, how about this:

diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c
index 2409e61..3bde700 100644
--- a/ext/fiddle/pointer.c
+++ b/ext/fiddle/pointer.c
@@ -137,11 +137,11 @@ fiddle_ptr_memory_view_available_p(VALUE obj)
 static bool
 fiddle_ptr_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
 {
-    bool writable_requested = flags & RUBY_MEMORY_VIEW_WRITABLE;
+    bool read_only = !(flags & RUBY_MEMORY_VIEW_WRITABLE);
     if (flags != RUBY_MEMORY_VIEW_SIMPLE && flags != RUBY_MEMORY_VIEW_WRITABLE) 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, !writable_requested);
+    rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, read_only);
 
     return true;
 }

Is this a YAGNI concern? You are the maintainer of this feature (I guess). What matters most is that it makes sense to you. If you don't agree with me, I will apply your suggestion.

Thank you.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern is if (flags != RUBY_MEMORY_VIEW_SIMPLE && flags != RUBY_MEMORY_VIEW_WRITABLE) return false; line. if (... != ... && ... != ...) return false (not, not, false) is difficult to understand.

Can we reduce negative parts as much as possible?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I assigned the check result of flags to a variable and pushed it. How about the current patch?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. Let's use it.

@kou
kou merged commit e6c49f9 into ruby:master Aug 23, 2026
67 checks passed
@KitaitiMakoto

Copy link
Copy Markdown
Contributor Author

Thank you for the review and merge.

@KitaitiMakoto
KitaitiMakoto deleted the ptr-mv-writable branch August 23, 2026 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants