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.

2 Likes

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.