kamulos
October 29, 2020, 10:51am
1
I am calling Rust code from C code. In the Rust code a &str is constructed from a pointer and a length. This is what I have now:
fn ptr_to_str(ptr: *const u8, len: usize) -> Option<&'static str> {
if ptr.is_null() {
return None;
}
let slice = unsafe { slice::from_raw_parts(ptr, len) };
str::from_utf8(slice).ok()
}
In this case it does not really matter that much, but I don't really like using the static lifetime. Is there a better alternative?
2e71828
October 29, 2020, 10:56am
2
You’d need to get the lifetime from somewhere else, for example:
unsafe fn ptr_to_str<'a, T:?Sized>(_virtual_owner: &'a T, ptr: *const u8, len: usize) -> Option<&'a str> {
if ptr.is_null() {
return None;
}
let slice = slice::from_raw_parts(ptr, len);
str::from_utf8(slice).ok()
}
Here, the compiler will prevent the returned &str from being used outside the region where _virtual_owner is a valid reference.
3 Likes
H2CO3
October 29, 2020, 10:57am
3
You can parameterize the function on the lifetime (fn ptr_to_str<'a>(…) -> &'a str). However, this does not change the fact that this is fundamentally unsafe. You should mark this function as unsafe.
2 Likes
Yandros
October 29, 2020, 12:20pm
4
2e71828:
_virtual_owner
A practical way to do this is to use the pointer itself as the owner, thus borrowing it rather than copying it:
unsafe
fn ptr_to_str<'ptr> (&ptr: &'ptr *const u8, len: usize)
-> Option<&'ptr str>
{
if ptr.is_null() {
return None;
}
let slice = slice::from_raw_parts(ptr, len);
str::from_utf8(slice).ok()
}
This will "ensure" your obtained &str can only be used within the body of the ffi-exported function, and no more (e.g. , because the FFI may immediately free the string when the function returns).
5 Likes
system
Closed
January 27, 2021, 12:20pm
5
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.