FFI help to thwart unwarranted protection

I have an allocation outside the rust heap and wish to mutate it under rust.
my problem is that there are some rust functions that require ownership of it which,
if I understand correctly, is no more than rust having the ability to drop() it, which is out of the question.
ManuallyDrop.take unfortunately does a copy, and into_inner requires ownership.
given that this is ffi and unsafe is par, is there a way to persuade rust to do *mut T -> T without copying and without auto drop?!

If the function takes ownership and gives it back, you can use std::ptr::read and std::ptr::write. Something like this:

unsafe fn do_stuff(p: *mut Foo) {
    let mut x = std::ptr::read(p);
    x = call_rust_fn(x);
    std::ptr::write(p, x);

(If the Rust code you call may panic, and Foo has destructors, then you also need to disable unwinding or use a technique like the take_mut crate to prevent double-drop on panic.)

If the function takes ownership and does not give it back, then it's not just able to drop the value; it does drop the value.

Note that ownership and dropping really matter only if the Rust type of the value has a destructor (or contains fields of type that do). Otherwise, dropping does not cause any observable side-effects.

With more details about the types and function signatures involved, their destructors, etc., we could probably give more specific suggestions.


Is it possible to change the Rust code to not require ownership and just take a reference instead? Otherwise you could convert the pointer to a reference and Clone it.

By definition, when you dereference a pointer it will copy the bytes behind the pointer to a variable on the stack.

Are you able to write up a simplified version of the problem on the playground? The problem might be easier to tackle if we can point to specific lines in code, and the process of writing up a simplified version of your problem can sometimes help you figure out how to solve it yourself.

indeed ptr::read/write looks just right.
is it then appropriate to .forget() the copied T after the ptr::write ?
ie. the T-copied is on the stack and will go out of scope without any destructors run
on it or its constituents.

It’s not necessary. ptr::write does the equivalent of forget.

1 Like

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.