[ruby-core:125684] [Ruby Feature#22102] C API to obtain a C string from a Ruby String
Issue #22102 has been reported by rhenium (Kazuki Yamaguchi). ---------------------------------------- Feature #22102: C API to obtain a C string from a Ruby String https://bugs.ruby-lang.org/issues/22102 * Author: rhenium (Kazuki Yamaguchi) * Status: Open ---------------------------------------- Extracted from https://bugs.ruby-lang.org/issues/19315#note-35 It would be nice to have a utility function whose sole purpose is to obtain a C string (NUL-terminated and containing no NUL bytes) from a Ruby String. I suggest adding something like the following to the public C API: ```c /** * Returns a pointer to the string contents as a C string. This checks that the * string does not contain embedded NUL bytes and that it is properly * NUL-terminated. * * @param[in] str String in question. * @exception rb_eArgError String contents include a NUL byte in the middle. * @return Pointer to its contents. * @pre `str` must be an instance of ::RString. */ const char *rb_str_cstr(VALUE str); ``` While extensions can currently use `StringValueCStr(val)`, there are cases where it's inconvenient. - The argument `val` needs to be addressable and modifiable, even if a type conversion is not needed. ```c const char *ptr = StringValueCStr(rb_ary_entry(ary, 0)); // Won't compile ``` - Repeating `StringValue*()` calls on the same object to perform different checks is awkward. ```c // Let's say, `val_a` and `val_b` are passed as an input, and the types are unknown StringValueCStr(val_a); // The result is unusable because the next line can invalidate it const char *b = StringValueCStr(val_b); // `val_b.to_str` can mutate `val_a` const char *a = StringValueCStr(val_a); // So you have to check `val_a` again ``` -- https://bugs.ruby-lang.org/
Issue #22102 has been updated by nobu (Nobuyoshi Nakada). Expose `rb_str_to_cstr`? ---------------------------------------- Feature #22102: C API to obtain a C string from a Ruby String https://bugs.ruby-lang.org/issues/22102#change-117554 * Author: rhenium (Kazuki Yamaguchi) * Status: Open ---------------------------------------- Extracted from https://bugs.ruby-lang.org/issues/19315#note-35 It would be nice to have a utility function whose sole purpose is to obtain a C string (NUL-terminated and containing no NUL bytes) from a Ruby String. I suggest adding something like the following to the public C API: ```c /** * Returns a pointer to the string contents as a C string. This checks that the * string does not contain embedded NUL bytes and that it is properly * NUL-terminated. * * @param[in] str String in question. * @exception rb_eArgError String contents include a NUL byte in the middle. * @return Pointer to its contents. * @pre `str` must be an instance of ::RString. */ const char *rb_str_cstr(VALUE str); ``` While extensions can currently use `StringValueCStr(val)`, there are cases where it's inconvenient. - The argument `val` needs to be addressable and modifiable, even if a type conversion is not needed. ```c const char *ptr = StringValueCStr(rb_ary_entry(ary, 0)); // Won't compile ``` - Repeating `StringValue*()` calls on the same object to perform different checks is awkward. ```c // Let's say, `val_a` and `val_b` are passed as an input, and the types are unknown StringValueCStr(val_a); // The result is unusable because the next line can invalidate it const char *b = StringValueCStr(val_b); // `val_b.to_str` can mutate `val_a` const char *a = StringValueCStr(val_a); // So you have to check `val_a` again ``` -- https://bugs.ruby-lang.org/
Issue #22102 has been updated by rhenium (Kazuki Yamaguchi). As @kou pointed out in <https://bugs.ruby-lang.org/issues/19315#note-36>, `rb_str_to_cstr()` in string.c returns NULL if the string is found to contain NUL bytes in the middle. IMO an exception more often is desirable for typical use cases in extensions, so my suggestion is to raise `ArgumentError`, similar to how `StringValueCStr()` currently behaves. I don't have a strong opinion on whether the public API should have "to_" in the name or not, but I have a mild preference for a shorter name. ---------------------------------------- Feature #22102: C API to obtain a C string from a Ruby String https://bugs.ruby-lang.org/issues/22102#change-117557 * Author: rhenium (Kazuki Yamaguchi) * Status: Open ---------------------------------------- Extracted from https://bugs.ruby-lang.org/issues/19315#note-35 It would be nice to have a utility function whose sole purpose is to obtain a C string (NUL-terminated and containing no NUL bytes) from a Ruby String. I suggest adding something like the following to the public C API: ```c /** * Returns a pointer to the string contents as a C string. This checks that the * string does not contain embedded NUL bytes and that it is properly * NUL-terminated. * * @param[in] str String in question. * @exception rb_eArgError String contents include a NUL byte in the middle. * @return Pointer to its contents. * @pre `str` must be an instance of ::RString. */ const char *rb_str_cstr(VALUE str); ``` While extensions can currently use `StringValueCStr(val)`, there are cases where it's inconvenient. - The argument `val` needs to be addressable and modifiable, even if a type conversion is not needed. ```c const char *ptr = StringValueCStr(rb_ary_entry(ary, 0)); // Won't compile ``` - Repeating `StringValue*()` calls on the same object to perform different checks is awkward. ```c // Let's say, `val_a` and `val_b` are passed as an input, and the types are unknown StringValueCStr(val_a); // The result is unusable because the next line can invalidate it const char *b = StringValueCStr(val_b); // `val_b.to_str` can mutate `val_a` const char *a = StringValueCStr(val_a); // So you have to check `val_a` again ``` -- https://bugs.ruby-lang.org/
Issue #22102 has been updated by nobu (Nobuyoshi Nakada). rhenium (Kazuki Yamaguchi) wrote:
* The argument `val` needs to be addressable and modifiable, even if a type conversion is not needed.
So the document needs another statement. ``` * @exception rb_eTypeError `str` is not an instance of ::RString. ``` ---------------------------------------- Feature #22102: C API to obtain a C string from a Ruby String https://bugs.ruby-lang.org/issues/22102#change-117921 * Author: rhenium (Kazuki Yamaguchi) * Status: Open ---------------------------------------- Extracted from https://bugs.ruby-lang.org/issues/19315#note-35 It would be nice to have a utility function whose sole purpose is to obtain a C string (NUL-terminated and containing no NUL bytes) from a Ruby String. I suggest adding something like the following to the public C API: ```c /** * Returns a pointer to the string contents as a C string. This checks that the * string does not contain embedded NUL bytes and that it is properly * NUL-terminated. * * @param[in] str String in question. * @exception rb_eArgError String contents include a NUL byte in the middle. * @return Pointer to its contents. * @pre `str` must be an instance of ::RString. */ const char *rb_str_cstr(VALUE str); ``` While extensions can currently use `StringValueCStr(val)`, there are cases where it's inconvenient. - The argument `val` needs to be addressable and modifiable, even if a type conversion is not needed. ```c const char *ptr = StringValueCStr(rb_ary_entry(ary, 0)); // Won't compile ``` - Repeating `StringValue*()` calls on the same object to perform different checks is awkward. ```c // Let's say, `val_a` and `val_b` are passed as an input, and the types are unknown StringValueCStr(val_a); // The result is unusable because the next line can invalidate it const char *b = StringValueCStr(val_b); // `val_b.to_str` can mutate `val_a` const char *a = StringValueCStr(val_a); // So you have to check `val_a` again ``` -- https://bugs.ruby-lang.org/
Issue #22102 has been updated by rhenium (Kazuki Yamaguchi). I prepared a GitHub PR: https://github.com/ruby/ruby/pull/17707 IMO we can just make it the user's responsibility to pass a `T_STRING`. I see this as a replacement for `RSTRING_PTR()` in cases where a C string is explicitly required. ---------------------------------------- Feature #22102: C API to obtain a C string from a Ruby String https://bugs.ruby-lang.org/issues/22102#change-117923 * Author: rhenium (Kazuki Yamaguchi) * Status: Open ---------------------------------------- Extracted from https://bugs.ruby-lang.org/issues/19315#note-35 It would be nice to have a utility function whose sole purpose is to obtain a C string (NUL-terminated and containing no NUL bytes) from a Ruby String. I suggest adding something like the following to the public C API: ```c /** * Returns a pointer to the string contents as a C string. This checks that the * string does not contain embedded NUL bytes and that it is properly * NUL-terminated. * * @param[in] str String in question. * @exception rb_eArgError String contents include a NUL byte in the middle. * @return Pointer to its contents. * @pre `str` must be an instance of ::RString. */ const char *rb_str_cstr(VALUE str); ``` While extensions can currently use `StringValueCStr(val)`, there are cases where it's inconvenient. - The argument `val` needs to be addressable and modifiable, even if a type conversion is not needed. ```c const char *ptr = StringValueCStr(rb_ary_entry(ary, 0)); // Won't compile ``` - Repeating `StringValue*()` calls on the same object to perform different checks is awkward. ```c // Let's say, `val_a` and `val_b` are passed as an input, and the types are unknown StringValueCStr(val_a); // The result is unusable because the next line can invalidate it const char *b = StringValueCStr(val_b); // `val_b.to_str` can mutate `val_a` const char *a = StringValueCStr(val_a); // So you have to check `val_a` again ``` -- https://bugs.ruby-lang.org/
Issue #22102 has been updated by Eregon (Benoit Daloze). +1, I think this is useful to add ---------------------------------------- Feature #22102: C API to obtain a C string from a Ruby String https://bugs.ruby-lang.org/issues/22102#change-117940 * Author: rhenium (Kazuki Yamaguchi) * Status: Open ---------------------------------------- Extracted from https://bugs.ruby-lang.org/issues/19315#note-35 It would be nice to have a utility function whose sole purpose is to obtain a C string (NUL-terminated and containing no NUL bytes) from a Ruby String. I suggest adding something like the following to the public C API: ```c /** * Returns a pointer to the string contents as a C string. This checks that the * string does not contain embedded NUL bytes and that it is properly * NUL-terminated. * * @param[in] str String in question. * @exception rb_eArgError String contents include a NUL byte in the middle. * @return Pointer to its contents. * @pre `str` must be an instance of ::RString. */ const char *rb_str_cstr(VALUE str); ``` While extensions can currently use `StringValueCStr(val)`, there are cases where it's inconvenient. - The argument `val` needs to be addressable and modifiable, even if a type conversion is not needed. ```c const char *ptr = StringValueCStr(rb_ary_entry(ary, 0)); // Won't compile ``` - Repeating `StringValue*()` calls on the same object to perform different checks is awkward. ```c // Let's say, `val_a` and `val_b` are passed as an input, and the types are unknown StringValueCStr(val_a); // The result is unusable because the next line can invalidate it const char *b = StringValueCStr(val_b); // `val_b.to_str` can mutate `val_a` const char *a = StringValueCStr(val_a); // So you have to check `val_a` again ``` -- https://bugs.ruby-lang.org/
Issue #22102 has been updated by kou (Kouhei Sutou). +1 ---------------------------------------- Feature #22102: C API to obtain a C string from a Ruby String https://bugs.ruby-lang.org/issues/22102#change-117941 * Author: rhenium (Kazuki Yamaguchi) * Status: Open ---------------------------------------- Extracted from https://bugs.ruby-lang.org/issues/19315#note-35 It would be nice to have a utility function whose sole purpose is to obtain a C string (NUL-terminated and containing no NUL bytes) from a Ruby String. I suggest adding something like the following to the public C API: ```c /** * Returns a pointer to the string contents as a C string. This checks that the * string does not contain embedded NUL bytes and that it is properly * NUL-terminated. * * @param[in] str String in question. * @exception rb_eArgError String contents include a NUL byte in the middle. * @return Pointer to its contents. * @pre `str` must be an instance of ::RString. */ const char *rb_str_cstr(VALUE str); ``` While extensions can currently use `StringValueCStr(val)`, there are cases where it's inconvenient. - The argument `val` needs to be addressable and modifiable, even if a type conversion is not needed. ```c const char *ptr = StringValueCStr(rb_ary_entry(ary, 0)); // Won't compile ``` - Repeating `StringValue*()` calls on the same object to perform different checks is awkward. ```c // Let's say, `val_a` and `val_b` are passed as an input, and the types are unknown StringValueCStr(val_a); // The result is unusable because the next line can invalidate it const char *b = StringValueCStr(val_b); // `val_b.to_str` can mutate `val_a` const char *a = StringValueCStr(val_a); // So you have to check `val_a` again ``` -- https://bugs.ruby-lang.org/
participants (4)
-
Eregon (Benoit Daloze) -
kou (Kouhei Sutou) -
nobu (Nobuyoshi Nakada) -
rhenium (Kazuki Yamaguchi)