Help with FFI (trait object)

hello folks,

I have a Box that gets taken control of by an outside runtime.
when it is offered back to rust it is in embedded in an allocation on the other runtime heap.
so it would be natural to refer to its location via a raw pointer or reference.
I need ownership and .forget() will be invoked on it but since it is non-Copy
the compiler disallows a de-referencing.
my question is how does one get back ownership of the trait object without copying?

If you know the other side (and generally nothing else) won't touch the pointee anymore (which is required to get true ownership of it), then you can ptr::read() a copy of it. That is, the following is sound:

let foo: Foo = Foo::new();
let ptr_to_foo: *mut Foo = ffi::taketh_and_giveth_back(foo);
// the pointee `Foo` will no longer be accessed by the FFI, but the pointer
// itself does not come from a `Box` allocation, so `Box<Foo>` is not right.
let foo: Foo = unsafe { ptr_too_foo.read() };
stuff(foo);

Justification

  1. The FFI side won't be dropping stuff unless told explicitely, so you can see that as if all the fields of all structs were wrapped inside ManuallyDrop<_>.

  2. The heap allocation from FFI could be seen as an FFIBox<_> smartpointer that implements DerefMut (by virtue of exclusive ownership).

  3. The pointer to our Foo thus originates from a FFIBox<StructWithField<ManuallyDrop<Foo>>>.
    By virtue of ownership over such FFIBox, and using DerefMut, we can get a &mut ManuallyDrop<Foo>.

Then, to take ownership of the Foo pointee, all we have to do is ManuallyDrop::take() it, i.e., ptr::read() it.

(Given the name of the thread, I suspect that Foo in my example is something like Box<dyn Trait + ...> in your case).

that did the trick - thanks.
I forgot to add the ticks and my type was indeed:

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.