|
63 | 63 | //! T` obtained from `Box::<T>::into_raw` may be deallocated using the
|
64 | 64 | //! [`Global`] allocator with `Layout::for_value(&*value)`.
|
65 | 65 | //!
|
66 |
| -//! `Box<T>` has the same ABI as `&mut T`. In particular, when `T: Sized`, |
67 |
| -//! this allows using `Box<T>` in FFI: |
| 66 | +//! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented as a |
| 67 | +//! single pointer and is also ABI-compatible with C pointers (i.e. the C type |
| 68 | +//! `T*`). This means that you have Rust code which passes ownership of a |
| 69 | +//! `Box<T>` to C code by using `Box<T>` as the type on the Rust side, and |
| 70 | +//! `T*` as the corresponding type on the C side. As an example, consider this |
| 71 | +//! C header which declares functions that create and destroy some kind of |
| 72 | +//! `Foo` value: |
68 | 73 | //!
|
69 | 74 | //! ```c
|
70 | 75 | //! /* C header */
|
71 | 76 | //! struct Foo* foo_new(void); /* Returns ownership to the caller */
|
72 | 77 | //! void foo_delete(struct Foo*); /* Takes ownership from the caller */
|
73 | 78 | //! ```
|
| 79 | +//! |
| 80 | +//! These two functions might be implemented in Rust as follows. Here, the |
| 81 | +//! `struct Foo*` type from C is translated to `Box<Foo>`, which captures |
| 82 | +//! the ownership constraints. Note also that the nullable argument to |
| 83 | +//! `foo_delete` is represented in Rust as `Option<Box<Foo>>`, since `Box<Foo>` |
| 84 | +//! cannot be null. |
74 | 85 | //!
|
75 | 86 | //! ```
|
76 | 87 | //! #[repr(C)]
|
|
84 | 95 | //! #[no_mangle]
|
85 | 96 | //! pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}
|
86 | 97 | //! ```
|
| 98 | +//! |
| 99 | +//! Even though `Box<T>` has the same representation and C ABI as a C pointer, |
| 100 | +//! this does not mean that you can convert an arbitrary `T*` into a `Box<T>` |
| 101 | +//! and expect things to work. `Box<T>` values will always be fully aligned, |
| 102 | +//! non-null pointers. Moreover, the destructor for `Box<T>` will attempt to |
| 103 | +//! free the value with the global allocator. In general, the best practice |
| 104 | +//! is to only use `Box<T>` for pointers that originated from the global |
| 105 | +//! allocator. |
87 | 106 | //!
|
88 | 107 | //! [dereferencing]: ../../std/ops/trait.Deref.html
|
89 | 108 | //! [`Box`]: struct.Box.html
|
|
0 commit comments