|
1 | 1 | /// A type for which the layout is determined by an external definition.
|
2 | 2 | ///
|
3 | 3 | /// `ExternType` makes it possible for CXX to safely share a consistent Rust type across multiple
|
4 |
| -/// #\[cxx::bridge\] invocations. This serves multiple related purposes. |
| 4 | +/// #\[cxx::bridge\] invocations, both for shared types defined in another bridge and external C++ |
| 5 | +/// definitions. This serves multiple related purposes. |
| 6 | +/// |
| 7 | +/// TODO: These docs aren't discoverable. Add a link to here from the main crate docs. |
5 | 8 | ///
|
6 | 9 | /// <br>
|
7 | 10 | ///
|
|
48 | 51 | ///
|
49 | 52 | /// <br><br>
|
50 | 53 | ///
|
| 54 | +/// ## Reusing Rust/C++ shared types across multiple bridges |
| 55 | +/// |
| 56 | +/// `ExternType` enables reusing a shared Rust/C++ type declared in another bridge module, allowing |
| 57 | +/// for the creation of libraries to wrap types used in multiple different bridges. |
| 58 | +/// |
| 59 | +/// Imagine we have an existing move-only C++ type, file::UniqueFd, that wraps sole ownership of a |
| 60 | +/// file descriptor, analogous to Rust's std::fd::File. The example below defines a shared type |
| 61 | +/// `File` that allows safely transferring ownership of the file across the interface without Box or |
| 62 | +/// UniquePtr and without resource leaks. This type can then be reused in other bridges. |
| 63 | +/// |
| 64 | +/// ```no_run |
| 65 | +/// // file/src/lib.rs |
| 66 | +/// # mod file { |
| 67 | +/// # use std::os::unix::io::{IntoRawFd, FromRawFd}; |
| 68 | +/// #[cxx::bridge(namespace = file::ffi)] |
| 69 | +/// pub mod ffi { |
| 70 | +/// /// A file backed by a file descriptor, which it is the sole owner of. |
| 71 | +/// struct File { |
| 72 | +/// fd: i32, |
| 73 | +/// } |
| 74 | +/// } |
| 75 | +/// |
| 76 | +/// impl From<ffi::File> for std::fs::File { |
| 77 | +/// fn from(value: ffi::File) -> Self { |
| 78 | +/// // Safe because ffi::File owns its file descriptor. |
| 79 | +/// unsafe { Self::from_raw_fd(value.fd) } |
| 80 | +/// } |
| 81 | +/// } |
| 82 | +/// |
| 83 | +/// impl From<std::fs::File> for ffi::File { |
| 84 | +/// fn from(value: std::fs::File) -> Self { |
| 85 | +/// Self { fd: value.into_raw_fd() } |
| 86 | +/// } |
| 87 | +/// } |
| 88 | +/// |
| 89 | +/// impl Drop for ffi::File { |
| 90 | +/// fn drop(&mut self) { |
| 91 | +/// // Safe because ffi::File owns its file descriptor. |
| 92 | +/// unsafe { std::fs::File::from_raw_fd(self.fd); } |
| 93 | +/// } |
| 94 | +/// } |
| 95 | +/// # } |
| 96 | +/// |
| 97 | +/// // file/src/lib.h |
| 98 | +/// # /* |
| 99 | +/// namespace file { |
| 100 | +/// |
| 101 | +/// ffi::File TransferToFFI(File file) { |
| 102 | +/// // Imagine file::UniqueFd::release() is analogous to from_raw_fd |
| 103 | +/// return ffi::File{ .fd = file.release() }; |
| 104 | +/// } |
| 105 | +/// |
| 106 | +/// } |
| 107 | +/// # */ |
| 108 | +/// |
| 109 | +/// // TODO(https://github.com/dtolnay/cxx/pull/298): Currently this bridge must use the same |
| 110 | +/// // namespace as any bridge it creates aliases from. |
| 111 | +/// |
| 112 | +/// // usage.rs |
| 113 | +/// # mod usage { |
| 114 | +/// #[cxx::bridge(namespace = file::ffi)] |
| 115 | +/// pub mod ffi { |
| 116 | +/// type File = crate::file::ffi::File; |
| 117 | +/// |
| 118 | +/// extern "C" { |
| 119 | +/// type Demo; |
| 120 | +/// |
| 121 | +/// fn create_demo(file: File) -> UniquePtr<Demo>; |
| 122 | +/// } |
| 123 | +/// } |
| 124 | +/// # } |
| 125 | +/// |
| 126 | +/// // usage.cc |
| 127 | +/// # /* |
| 128 | +/// file::ffi::File ConvertFile(file::UniqueFd file) { |
| 129 | +/// } |
| 130 | +/// |
| 131 | +/// void CreateDemo(file::UniqueFd file) { |
| 132 | +/// auto demo = ffi::create_demo(file::TransferToFFI(std::move(file))); |
| 133 | +/// // use demo |
| 134 | +/// } |
| 135 | +/// # */ |
| 136 | +/// |
| 137 | +/// # fn main() {} |
| 138 | +/// ``` |
| 139 | +/// |
| 140 | +/// <br><br> |
| 141 | +/// |
51 | 142 | /// ## Integrating with bindgen-generated types
|
52 | 143 | ///
|
53 | 144 | /// Handwritten `ExternType` impls make it possible to plug in a data structure emitted by bindgen
|
|
0 commit comments