flapigen-rs icon indicating copy to clipboard operation
flapigen-rs copied to clipboard

c++/smart ptr and vec

Open Dushistov opened this issue 4 years ago • 2 comments

Fix Vec<SmartPtr> case. Vec<Rc<RefCell<X>> works while should not, Vec<Arc<X>> doesn't work.

Dushistov avatar Sep 02 '19 22:09 Dushistov

I've recently bump into this. AFAIK the problem is, CRustForeignVec::from_vec, should iterate through the Vec and run box_object on all items, before it creates CRustForeignVec. Reverse operation should be done in drop_foreign_class_vec. In fact, I can try to implement PR for this.

BTW, I have a problem with understanding those CRustVec and CRustForeignVec structs. If I understand correctly, the first one is intended for primitive types, like uint, the second one, for SwigForeignClasses. How about types that requires foreign_typemap conversion, like tuples, Options, etc? Can they be used with Vec? How to adjust CRustForeignVec to accept such types?

AdamRzepka avatar Apr 29 '20 08:04 AdamRzepka

I've recently bump into this. AFAIK the problem is, CRustForeignVec::from_vec, should iterate through the Vec and run box_object on all items, before it creates CRustForeignVec. Reverse operation should be done in drop_foreign_class_vec. In fact, I can try to implement PR for this.

Not exactly. Case, when type T exported as Box<T> is special. Because it is possible to create C++ class from Vec<T> directly, because of Box::into_raw and &Vec<T>[index] is the same thing.

But in case of Vec<T> and OtherSmartPtr<T> it is impossible to get the same thing from OtherSmartPtr::from_raw and &Vec<T>[index] (it would be the same type, but when you call into_raw for &Vec[index] it would be UB).

In case of Vec<OtherSmartPtr<T>> and OtherSmartPtr<T>, the problem is that index operation is very tricky. I suppose C++ RustForeignVec in that case can not handle index operation in C++ part and should use Rust code for clone and into_raw calls.

BTW, I have a problem with understanding those CRustVec and CRustForeignVec structs. If I understand correctly, the first one is intended for primitive types, like uint, the second one, for SwigForeignClasses.

The main difference is step field, it is impossible to calculate std::mem::size_of in cross-compilation case in general. It is possible for primitive types, so CRustVec is some kind of optimization.

Summary: CRustVec and CRustForeignVec are for cases when you can use directly Vec<T> without additional memory allocations and without extra efforts.

For other cases: I just use foreign_class for Vec, like:

foreign_class!(
class Boo {
self_type Vec<Arc<Foo>>;
fn index(&self, i: usize) -> ...

Dushistov avatar Apr 29 '20 09:04 Dushistov