I have a c-function that returns a ptr to a string, but I do not know how long it will live, so I want to create a copy of it and return a String in my safe wrapper.
Seems reasonable to me, but why the unwrap() if you are already returning an Option? You could use .map(str::to_owned) instead. (And I'd suggest to_owned() because it might be slightly more efficient as it doesn't need to go through the Display impl in the absence of specialization).
That changes the behaviour when not utf-8. A silent None makes debugging hard. Using to_string_lossy maybe best; depends how you want to define robust. For performant there is std::str::from_utf8_unchecked.
It's not that it "would communicate better". Not marking this function unsafe is simply incorrect, since safe Rust must not ever invoke undefined behavior, and calling this function with non-null dangling pointer is undefined behavior.
Yes, I'm aware, and returning None, which is expected of an Option-returning function, is superior to panicking sometimes, which is absolutely unexpected from a function that seemingly supports graceful error handling.
Citation needed. What's "silent" about that? It's a completely explicit thing, and you can always break on the None case in a debugger…
Well, in this case it might be more correct to return Result<String, TakeOwnershipError>, with TakeOwnershipError being the enum with variants NullPtrError and Utf8Error.