On Wed, Jul 19, 2023 at 09:09:51AM +0000, Tage Johansson wrote:+fn test_connect_command() { + let nbd = libnbd::Handle::new().unwrap(); + nbd.connect_command(&[ + c_str!("nbdkit"), + c_str!("-s"), + c_str!("--exit-with-parent"), + c_str!("-v"), + c_str!("null"), + ]) + .unwrap();So this doesn't seem very natural Rust to me. For example standard library exec::execvp lets you just use: let err = exec::execvp("echo", &["echo", "foo"]); println!("Error: {}", err); (https://docs.rs/exec/latest/exec/fn.execvp.html) Is there a way to get rid of the c_str macro here?
Yes, there is, but it would require cloning every string. The problem is that Libnbd uses null terminated strings and Rust uses "Vector like" strings with a stored length (as C++'s `String` type). So a rust string literal (`str`) like `"nbdkit"` is stored as an array of length 6 bytes without a NULL at the end, and the integer `6` to tell the length. (See here for more explonations.) The thing is that to convert an `&str` to a null terminated string (`&CStr`) it must be cloned to make room for the extra NULL character.
One would need to use something like `impl Into<Vec<u8>>` instead of `&CStr` as type of the string arguments, and then convert it to a null terminated string with `CString::new()`.
Since these conversions would only take place when the user creates or configures the handle, the extra cost shouldn't be a problem in most cases, and I can definitely change this. But it doesn't become zero cost abstraction.
Best regards,
Tage
So to summerize: I can change the type of strings that are sent
to Libnbd so that the `c_str!(...)` macro wouldn't be needed,
although that would require cloning every string. But I'd rather
keep the type of strings going
Rich.