let cstring = CString::new("my string").unwrap();
let cstr = unsafe { CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul()) };
let ptr = cstr.as_ptr();
let inst = ngx_str_t {
len: "my string".len(),
data: ptr as (*mut u_char),
};
If you pass the string as a pointer and length, I don't think you need CString at all. You can just pass rust_string.as_ptr() as *mut u_char.
You just need to make sure that the other end is ok with UTF-8 encoded data.
You need to at least forget the original (C)String, otherwise the data the pointer points to gets deallocated as soon as the scope ends.
You also need to ensure that the string is not deallocated on the nginx-side, but instead is passed back into your Rust code for deallocation.
CString::into_raw is more explicit than as_ptr + mem::forget when you want the receiving code to take ownership of the buffer.
The String equivalent is .into_boxed_str().into_raw(), which also releases any excess capacity. You must do this if you want the receiving code to eventually destroy the buffer, unless you keep track of the capacity in some other way.
If you want the receiving code to destroy the buffer you must also be overriding the global allocator so that it's using the same allocator in both places, if you are doing that then having some excess capacity doesn't matter as the allocator is tracking that data per allocation anyway.
Oh, you were referring to some other Rust code receiving it back from the FFI code. Yes, in that case you do need to pass the capacity as well (which is easiest by making it equal to the length). I misunderstood what you meant by "receiving code".