1 | //! A framework for Rust wrappers over C APIs. |
2 | //! |
3 | //! Ownership is as important in C as it is in Rust, but the semantics are often implicit. In |
4 | //! particular, pointer-to-value is commonly used to pass C values both when transferring ownership |
5 | //! or a borrow. |
6 | //! |
7 | //! This crate provides a framework to define a Rust wrapper over these kinds of raw C APIs in a way |
8 | //! that allows ownership semantics to be expressed in an ergonomic manner. The framework takes a |
9 | //! dual-type approach similar to APIs in the standard library such as `PathBuf`/`Path` or `String`/ |
10 | //! `str`. One type represents an owned value and references to the other represent borrowed |
11 | //! values. |
12 | //! |
13 | //! # Examples |
14 | //! |
15 | //! ``` |
16 | //! use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; |
17 | //! use std::ops::{Deref, DerefMut}; |
18 | //! |
19 | //! mod foo_sys { |
20 | //! pub enum FOO {} |
21 | //! |
22 | //! extern { |
23 | //! pub fn FOO_free(foo: *mut FOO); |
24 | //! } |
25 | //! } |
26 | //! |
27 | //! // The borrowed type is a newtype wrapper around an `Opaque` value. |
28 | //! // |
29 | //! // `FooRef` values never exist; we instead create references to `FooRef`s |
30 | //! // from raw C pointers. |
31 | //! pub struct FooRef(Opaque); |
32 | //! |
33 | //! impl ForeignTypeRef for FooRef { |
34 | //! type CType = foo_sys::FOO; |
35 | //! } |
36 | //! |
37 | //! // The owned type is simply a newtype wrapper around the raw C type. |
38 | //! // |
39 | //! // It dereferences to `FooRef`, so methods that do not require ownership |
40 | //! // should be defined there. |
41 | //! pub struct Foo(*mut foo_sys::FOO); |
42 | //! |
43 | //! impl Drop for Foo { |
44 | //! fn drop(&mut self) { |
45 | //! unsafe { foo_sys::FOO_free(self.0) } |
46 | //! } |
47 | //! } |
48 | //! |
49 | //! impl ForeignType for Foo { |
50 | //! type CType = foo_sys::FOO; |
51 | //! type Ref = FooRef; |
52 | //! |
53 | //! unsafe fn from_ptr(ptr: *mut foo_sys::FOO) -> Foo { |
54 | //! Foo(ptr) |
55 | //! } |
56 | //! |
57 | //! fn as_ptr(&self) -> *mut foo_sys::FOO { |
58 | //! self.0 |
59 | //! } |
60 | //! } |
61 | //! |
62 | //! impl Deref for Foo { |
63 | //! type Target = FooRef; |
64 | //! |
65 | //! fn deref(&self) -> &FooRef { |
66 | //! unsafe { FooRef::from_ptr(self.0) } |
67 | //! } |
68 | //! } |
69 | //! |
70 | //! impl DerefMut for Foo { |
71 | //! fn deref_mut(&mut self) -> &mut FooRef { |
72 | //! unsafe { FooRef::from_ptr_mut(self.0) } |
73 | //! } |
74 | //! } |
75 | //! ``` |
76 | //! |
77 | //! The `foreign_type!` macro can generate this boilerplate for you: |
78 | //! |
79 | //! ``` |
80 | //! #[macro_use] |
81 | //! extern crate foreign_types; |
82 | //! |
83 | //! mod foo_sys { |
84 | //! pub enum FOO {} |
85 | //! |
86 | //! extern { |
87 | //! pub fn FOO_free(foo: *mut FOO); |
88 | //! pub fn FOO_duplicate(foo: *mut FOO) -> *mut FOO; // Optional |
89 | //! } |
90 | //! } |
91 | //! |
92 | //! foreign_type! { |
93 | //! type CType = foo_sys::FOO; |
94 | //! fn drop = foo_sys::FOO_free; |
95 | //! fn clone = foo_sys::FOO_duplicate; // Optional |
96 | //! /// A Foo. |
97 | //! pub struct Foo; |
98 | //! /// A borrowed Foo. |
99 | //! pub struct FooRef; |
100 | //! } |
101 | //! |
102 | //! # fn main() {} |
103 | //! ``` |
104 | //! |
105 | //! If `fn clone` is specified, then it must take `CType` as an argument and return a copy of it as `CType`. |
106 | //! It will be used to implement `ToOwned` and `Clone`. |
107 | //! |
108 | //! `#[derive(…)] is permitted before the lines with `pub struct`. |
109 | //! `#[doc(hidden)]` before the `type CType` line will hide the `foreign_type!` implementations from documentation. |
110 | //! |
111 | //! Say we then have a separate type in our C API that contains a `FOO`: |
112 | //! |
113 | //! ``` |
114 | //! mod foo_sys { |
115 | //! pub enum FOO {} |
116 | //! pub enum BAR {} |
117 | //! |
118 | //! extern { |
119 | //! pub fn FOO_free(foo: *mut FOO); |
120 | //! pub fn BAR_free(bar: *mut BAR); |
121 | //! pub fn BAR_get_foo(bar: *mut BAR) -> *mut FOO; |
122 | //! } |
123 | //! } |
124 | //! ``` |
125 | //! |
126 | //! The documentation for the C library states that `BAR_get_foo` returns a reference into the `BAR` |
127 | //! passed to it, which translates into a reference in Rust. It also says that we're allowed to |
128 | //! modify the `FOO`, so we'll define a pair of accessor methods, one immutable and one mutable: |
129 | //! |
130 | //! ``` |
131 | //! #[macro_use] |
132 | //! extern crate foreign_types; |
133 | //! |
134 | //! use foreign_types::ForeignTypeRef; |
135 | //! |
136 | //! mod foo_sys { |
137 | //! pub enum FOO {} |
138 | //! pub enum BAR {} |
139 | //! |
140 | //! extern { |
141 | //! pub fn FOO_free(foo: *mut FOO); |
142 | //! pub fn BAR_free(bar: *mut BAR); |
143 | //! pub fn BAR_get_foo(bar: *mut BAR) -> *mut FOO; |
144 | //! } |
145 | //! } |
146 | //! |
147 | //! foreign_type! { |
148 | //! #[doc(hidden)] |
149 | //! type CType = foo_sys::FOO; |
150 | //! fn drop = foo_sys::FOO_free; |
151 | //! /// A Foo. |
152 | //! pub struct Foo; |
153 | //! /// A borrowed Foo. |
154 | //! pub struct FooRef; |
155 | //! } |
156 | //! |
157 | //! foreign_type! { |
158 | //! type CType = foo_sys::BAR; |
159 | //! fn drop = foo_sys::BAR_free; |
160 | //! /// A Foo. |
161 | //! pub struct Bar; |
162 | //! /// A borrowed Bar. |
163 | //! pub struct BarRef; |
164 | //! } |
165 | //! |
166 | //! impl BarRef { |
167 | //! fn foo(&self) -> &FooRef { |
168 | //! unsafe { FooRef::from_ptr(foo_sys::BAR_get_foo(self.as_ptr())) } |
169 | //! } |
170 | //! |
171 | //! fn foo_mut(&mut self) -> &mut FooRef { |
172 | //! unsafe { FooRef::from_ptr_mut(foo_sys::BAR_get_foo(self.as_ptr())) } |
173 | //! } |
174 | //! } |
175 | //! |
176 | //! # fn main() {} |
177 | //! ``` |
178 | #![no_std ] |
179 | #![warn (missing_docs)] |
180 | #![doc (html_root_url="https://docs.rs/foreign-types/0.3" )] |
181 | extern crate foreign_types_shared; |
182 | |
183 | #[doc (inline)] |
184 | pub use foreign_types_shared::*; |
185 | |
186 | /// A macro to easily define wrappers for foreign types. |
187 | /// |
188 | /// # Examples |
189 | /// |
190 | /// ``` |
191 | /// #[macro_use] |
192 | /// extern crate foreign_types; |
193 | /// |
194 | /// # mod openssl_sys { pub type SSL = (); pub unsafe fn SSL_free(_: *mut SSL) {} pub unsafe fn SSL_dup(x: *mut SSL) -> *mut SSL {x} } |
195 | /// foreign_type! { |
196 | /// type CType = openssl_sys::SSL; |
197 | /// fn drop = openssl_sys::SSL_free; |
198 | /// fn clone = openssl_sys::SSL_dup; |
199 | /// /// Documentation for the owned type. |
200 | /// pub struct Ssl; |
201 | /// /// Documentation for the borrowed type. |
202 | /// pub struct SslRef; |
203 | /// } |
204 | /// |
205 | /// # fn main() {} |
206 | /// ``` |
207 | #[macro_export ] |
208 | macro_rules! foreign_type { |
209 | ( |
210 | $(#[$impl_attr:meta])* |
211 | type CType = $ctype:ty; |
212 | fn drop = $drop:expr; |
213 | $(fn clone = $clone:expr;)* |
214 | $(#[$owned_attr:meta])* |
215 | pub struct $owned:ident; |
216 | $(#[$borrowed_attr:meta])* |
217 | pub struct $borrowed:ident; |
218 | ) => { |
219 | $(#[$owned_attr])* |
220 | pub struct $owned(*mut $ctype); |
221 | |
222 | $(#[$impl_attr])* |
223 | impl $crate::ForeignType for $owned { |
224 | type CType = $ctype; |
225 | type Ref = $borrowed; |
226 | |
227 | #[inline] |
228 | unsafe fn from_ptr(ptr: *mut $ctype) -> $owned { |
229 | $owned(ptr) |
230 | } |
231 | |
232 | #[inline] |
233 | fn as_ptr(&self) -> *mut $ctype { |
234 | self.0 |
235 | } |
236 | } |
237 | |
238 | impl Drop for $owned { |
239 | #[inline] |
240 | fn drop(&mut self) { |
241 | unsafe { $drop(self.0) } |
242 | } |
243 | } |
244 | |
245 | $( |
246 | impl Clone for $owned { |
247 | #[inline] |
248 | fn clone(&self) -> $owned { |
249 | unsafe { |
250 | let handle: *mut $ctype = $clone(self.0); |
251 | $crate::ForeignType::from_ptr(handle) |
252 | } |
253 | } |
254 | } |
255 | |
256 | impl ::std::borrow::ToOwned for $borrowed { |
257 | type Owned = $owned; |
258 | #[inline] |
259 | fn to_owned(&self) -> $owned { |
260 | unsafe { |
261 | let handle: *mut $ctype = $clone($crate::ForeignTypeRef::as_ptr(self)); |
262 | $crate::ForeignType::from_ptr(handle) |
263 | } |
264 | } |
265 | } |
266 | )* |
267 | |
268 | impl ::std::ops::Deref for $owned { |
269 | type Target = $borrowed; |
270 | |
271 | #[inline] |
272 | fn deref(&self) -> &$borrowed { |
273 | unsafe { $crate::ForeignTypeRef::from_ptr(self.0) } |
274 | } |
275 | } |
276 | |
277 | impl ::std::ops::DerefMut for $owned { |
278 | #[inline] |
279 | fn deref_mut(&mut self) -> &mut $borrowed { |
280 | unsafe { $crate::ForeignTypeRef::from_ptr_mut(self.0) } |
281 | } |
282 | } |
283 | |
284 | impl ::std::borrow::Borrow<$borrowed> for $owned { |
285 | #[inline] |
286 | fn borrow(&self) -> &$borrowed { |
287 | &**self |
288 | } |
289 | } |
290 | |
291 | impl ::std::convert::AsRef<$borrowed> for $owned { |
292 | #[inline] |
293 | fn as_ref(&self) -> &$borrowed { |
294 | &**self |
295 | } |
296 | } |
297 | |
298 | $(#[$borrowed_attr])* |
299 | pub struct $borrowed($crate::Opaque); |
300 | |
301 | $(#[$impl_attr])* |
302 | impl $crate::ForeignTypeRef for $borrowed { |
303 | type CType = $ctype; |
304 | } |
305 | } |
306 | } |
307 | |