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/