Skip to content

Commit b13bbf7

Browse files
committed
Add docs for shared type aliases
1 parent 229351c commit b13bbf7

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

src/extern_type.rs

+92-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
/// A type for which the layout is determined by an external definition.
22
///
33
/// `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.
58
///
69
/// <br>
710
///
@@ -48,6 +51,94 @@
4851
///
4952
/// <br><br>
5053
///
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+
///
51142
/// ## Integrating with bindgen-generated types
52143
///
53144
/// Handwritten `ExternType` impls make it possible to plug in a data structure emitted by bindgen

0 commit comments

Comments
 (0)