I'm giving an Arc::into_raw() pointer to C. Later, when I get the raw pointer back, I need to clone the Arc to increase its refcount and get an owned copy. What's the right way to do this?
Arc<T> is nice enough that a raw pointer it gives is *const T. However, this means that dereference of that pointer is not the Arc any more, so (*ptr).clone() is not the Arc::clone.
I came up with this, but it looks awkward:
let arc = unsafe {
let tmp = Arc::from_raw(pointer);
let arc = Arc::clone(&tmp);
let _ = Arc::into_raw(tmp);
arc
};
Why don't you clone the Arc when initially passing the pointer to C? i.e. not trying to bump the reference count after the fact.
That way you're creating a copy (bumping the reference count) then passing a raw pointer to some other code. At some time later on the C code will invoke a destructor function that would call Arc::from_raw() and immediately let the Arc go out of scope, decrementing the reference count again.
Yeah, initially I already return an object with refcount=1. However, in this case I'm also spawning a thread, which the C side technically doesn't know about, so it could tell me to free the whole object before my thread has finished. Plus, it's just safer to use safe constructs instead of trying to get away with raw pointers.
(I've tried a design that doesn't spawn hidden threads in Rust, and made the C side to deal with threading, but C programmers really didn't like that).