6
votes

I need to pass a raw pointer to a struct to C++ and then still want to use that box afterwards.

I found the into_raw function but it eats the box and I can't use that box any more in Rust. Is there a way to get a *const T? I could get away with const_cast on C++ side.

This is what I'm trying to do:

let handle_ptr = Box::<Handle>::into_raw(handle);            
     
     
std::thread::spawn(move || {            
    let rt = tokio::runtime::Builder::new_current_thread()            
        .build()            
        .unwrap();             
     
    rt.block_on( handle.run() );            
});            
     
return handle_ptr

I know that this is unsafe but I don't know any other way to allow C++ code running on other thread to call a thread-safe method of a Rust object.

1
Keeping the Box around after you've passed a pointer to another thread would allow you to drop it while the other thread is still running. How do you avoid that problem?trent ᶠᵒʳᵐᵉʳˡʸ ᶜˡ

1 Answers

7
votes

You can dereference the box and cast the reference to its contents as a raw pointer:

let handle_ptr: *const Handle = &*handle;

Or:

let handle_ptr = &*handle as *const Handle;

Note that you haven't had to use unsafe yet. You'll need to use unsafe to dereference this pointer, including passing it to your C++ function. When you use unsafe the compiler can't help you, and it's up to you to ensure that Undefined Behaviour isn't triggered, which includes checking safe code that affects memory that's accessed in unsafe code.

In this case, your C++ function may use the pointer after the box is dropped (use after free). It's therefore up to you to make sure that this cannot happen.


See examples in the documentation for raw pointers: