Feature #22102
openC API to obtain a C string from a Ruby String
Description
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:
/**
* 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
valneeds to be addressable and modifiable, even if a type conversion is not needed.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.// 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
Updated by nobu (Nobuyoshi Nakada) 4 days ago
Expose rb_str_to_cstr?
Updated by rhenium (Kazuki Yamaguchi) 4 days ago
As @kou (Kouhei Sutou) 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.