1
+ //! Platform-specific types, as defined by C.
2
+ //!
3
+ //! Code that interacts via FFI will almost certainly be using the
4
+ //! base types provided by C, which aren't nearly as nicely defined
5
+ //! as Rust's primitive types. This module provides types which will
6
+ //! match those defined by C, so that code that interacts with C will
7
+ //! refer to the correct types.
8
+
1
9
#![ stable( feature = "" , since = "1.30.0" ) ]
2
10
#![ allow( non_camel_case_types) ]
3
11
4
- //! Utilities related to foreign function interface (FFI) bindings.
5
-
6
12
use crate :: fmt;
7
13
use crate :: marker:: PhantomData ;
14
+ use crate :: num:: * ;
8
15
use crate :: ops:: { Deref , DerefMut } ;
9
16
10
- /// Equivalent to C's `void` type when used as a [pointer].
11
- ///
12
- /// In essence, `*const c_void` is equivalent to C's `const void*`
13
- /// and `*mut c_void` is equivalent to C's `void*`. That said, this is
14
- /// *not* the same as C's `void` return type, which is Rust's `()` type.
17
+ macro_rules! type_alias_no_nz {
18
+ {
19
+ $Docfile: tt, $Alias: ident = $Real: ty;
20
+ $( $Cfg: tt ) *
21
+ } => {
22
+ #[ doc = include_str!( $Docfile) ]
23
+ $( $Cfg ) *
24
+ #[ unstable( feature = "core_ffi_c" , issue = "94501" ) ]
25
+ pub type $Alias = $Real;
26
+ }
27
+ }
28
+
29
+ // To verify that the NonZero types in this file's macro invocations correspond
30
+ //
31
+ // perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
32
+ //
33
+ // NB this does not check that the main c_* types are right.
34
+
35
+ macro_rules! type_alias {
36
+ {
37
+ $Docfile: tt, $Alias: ident = $Real: ty, $NZAlias: ident = $NZReal: ty;
38
+ $( $Cfg: tt ) *
39
+ } => {
40
+ type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg ) * }
41
+
42
+ #[ doc = concat!( "Type alias for `NonZero` version of [`" , stringify!( $Alias) , "`]" ) ]
43
+ #[ unstable( feature = "raw_os_nonzero" , issue = "82363" ) ]
44
+ $( $Cfg ) *
45
+ pub type $NZAlias = $NZReal;
46
+ }
47
+ }
48
+
49
+ type_alias ! { "c_char.md" , c_char = c_char_definition:: c_char, NonZero_c_char = c_char_definition:: NonZero_c_char ;
50
+ // Make this type alias appear cfg-dependent so that Clippy does not suggest
51
+ // replacing `0 as c_char` with `0_i8`/`0_u8`. This #[cfg(all())] can be removed
52
+ // after the false positive in https://github.com/rust-lang/rust-clippy/issues/8093
53
+ // is fixed.
54
+ #[ cfg( all( ) ) ]
55
+ #[ doc( cfg( all( ) ) ) ] }
56
+ type_alias ! { "c_schar.md" , c_schar = i8 , NonZero_c_schar = NonZeroI8 ; }
57
+ type_alias ! { "c_uchar.md" , c_uchar = u8 , NonZero_c_uchar = NonZeroU8 ; }
58
+ type_alias ! { "c_short.md" , c_short = i16 , NonZero_c_short = NonZeroI16 ; }
59
+ type_alias ! { "c_ushort.md" , c_ushort = u16 , NonZero_c_ushort = NonZeroU16 ; }
60
+ type_alias ! { "c_int.md" , c_int = i32 , NonZero_c_int = NonZeroI32 ; }
61
+ type_alias ! { "c_uint.md" , c_uint = u32 , NonZero_c_uint = NonZeroU32 ; }
62
+ type_alias ! { "c_long.md" , c_long = i32 , NonZero_c_long = NonZeroI32 ;
63
+ #[ doc( cfg( all( ) ) ) ]
64
+ #[ cfg( any( target_pointer_width = "32" , windows) ) ] }
65
+ type_alias ! { "c_ulong.md" , c_ulong = u32 , NonZero_c_ulong = NonZeroU32 ;
66
+ #[ doc( cfg( all( ) ) ) ]
67
+ #[ cfg( any( target_pointer_width = "32" , windows) ) ] }
68
+ type_alias ! { "c_long.md" , c_long = i64 , NonZero_c_long = NonZeroI64 ;
69
+ #[ doc( cfg( all( ) ) ) ]
70
+ #[ cfg( all( target_pointer_width = "64" , not( windows) ) ) ] }
71
+ type_alias ! { "c_ulong.md" , c_ulong = u64 , NonZero_c_ulong = NonZeroU64 ;
72
+ #[ doc( cfg( all( ) ) ) ]
73
+ #[ cfg( all( target_pointer_width = "64" , not( windows) ) ) ] }
74
+ type_alias ! { "c_longlong.md" , c_longlong = i64 , NonZero_c_longlong = NonZeroI64 ; }
75
+ type_alias ! { "c_ulonglong.md" , c_ulonglong = u64 , NonZero_c_ulonglong = NonZeroU64 ; }
76
+ type_alias_no_nz ! { "c_float.md" , c_float = f32 ; }
77
+ type_alias_no_nz ! { "c_double.md" , c_double = f64 ; }
78
+
79
+ /// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
15
80
///
16
- /// To model pointers to opaque types in FFI, until `extern type` is
17
- /// stabilized, it is recommended to use a newtype wrapper around an empty
18
- /// byte array. See the [Nomicon] for details.
81
+ /// This type is currently always [`usize`], however in the future there may be
82
+ /// platforms where this is not the case.
83
+ #[ unstable( feature = "c_size_t" , issue = "88345" ) ]
84
+ pub type c_size_t = usize ;
85
+
86
+ /// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
19
87
///
20
- /// One could use `std::os::raw::c_void` if they want to support old Rust
21
- /// compiler down to 1.1.0. After Rust 1.30.0, it was re-exported by
22
- /// this definition. For more information, please read [RFC 2521].
88
+ /// This type is currently always [`isize`], however in the future there may be
89
+ /// platforms where this is not the case.
90
+ #[ unstable( feature = "c_size_t" , issue = "88345" ) ]
91
+ pub type c_ptrdiff_t = isize ;
92
+
93
+ /// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
23
94
///
24
- /// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
25
- /// [RFC 2521]: https://github.com/rust-lang/rfcs/blob/master/text/2521-c_void-reunification.md
95
+ /// This type is currently always [`isize`], however in the future there may be
96
+ /// platforms where this is not the case.
97
+ #[ unstable( feature = "c_size_t" , issue = "88345" ) ]
98
+ pub type c_ssize_t = isize ;
99
+
100
+ mod c_char_definition {
101
+ cfg_if ! {
102
+ // These are the targets on which c_char is unsigned.
103
+ if #[ cfg( any(
104
+ all(
105
+ target_os = "linux" ,
106
+ any(
107
+ target_arch = "aarch64" ,
108
+ target_arch = "arm" ,
109
+ target_arch = "hexagon" ,
110
+ target_arch = "powerpc" ,
111
+ target_arch = "powerpc64" ,
112
+ target_arch = "s390x" ,
113
+ target_arch = "riscv64" ,
114
+ target_arch = "riscv32"
115
+ )
116
+ ) ,
117
+ all( target_os = "android" , any( target_arch = "aarch64" , target_arch = "arm" ) ) ,
118
+ all( target_os = "l4re" , target_arch = "x86_64" ) ,
119
+ all(
120
+ target_os = "freebsd" ,
121
+ any(
122
+ target_arch = "aarch64" ,
123
+ target_arch = "arm" ,
124
+ target_arch = "powerpc" ,
125
+ target_arch = "powerpc64" ,
126
+ target_arch = "riscv64"
127
+ )
128
+ ) ,
129
+ all(
130
+ target_os = "netbsd" ,
131
+ any( target_arch = "aarch64" , target_arch = "arm" , target_arch = "powerpc" )
132
+ ) ,
133
+ all( target_os = "openbsd" , target_arch = "aarch64" ) ,
134
+ all(
135
+ target_os = "vxworks" ,
136
+ any(
137
+ target_arch = "aarch64" ,
138
+ target_arch = "arm" ,
139
+ target_arch = "powerpc64" ,
140
+ target_arch = "powerpc"
141
+ )
142
+ ) ,
143
+ all( target_os = "fuchsia" , target_arch = "aarch64" )
144
+ ) ) ] {
145
+ pub type c_char = u8 ;
146
+ pub type NonZero_c_char = crate :: num:: NonZeroU8 ;
147
+ } else {
148
+ // On every other target, c_char is signed.
149
+ pub type c_char = i8 ;
150
+ pub type NonZero_c_char = crate :: num:: NonZeroI8 ;
151
+ }
152
+ }
153
+ }
154
+
26
155
// N.B., for LLVM to recognize the void pointer type and by extension
27
156
// functions like malloc(), we need to have it represented as i8* in
28
157
// LLVM bitcode. The enum used here ensures this and prevents misuse
@@ -31,6 +160,7 @@ use crate::ops::{Deref, DerefMut};
31
160
// otherwise and we need at least one variant as otherwise the enum
32
161
// would be uninhabited and at least dereferencing such pointers would
33
162
// be UB.
163
+ #[ doc = include_str ! ( "c_void.md" ) ]
34
164
#[ repr( u8 ) ]
35
165
#[ stable( feature = "core_c_void" , since = "1.30.0" ) ]
36
166
pub enum c_void {
0 commit comments