]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | # External blocks |
2 | ||
0bf4aa26 XL |
3 | > **<sup>Syntax</sup>**\ |
4 | > _ExternBlock_ :\ | |
29967ef6 | 5 | > `unsafe`<sup>?</sup> `extern` [_Abi_]<sup>?</sup> `{`\ |
0bf4aa26 XL |
6 | > [_InnerAttribute_]<sup>\*</sup>\ |
7 | > _ExternalItem_<sup>\*</sup>\ | |
8 | > `}` | |
9 | > | |
10 | > _ExternalItem_ :\ | |
e74abb32 XL |
11 | > [_OuterAttribute_]<sup>\*</sup> (\ |
12 | > [_MacroInvocationSemi_]\ | |
13 | > | ( [_Visibility_]<sup>?</sup> ( _ExternalStaticItem_ | _ExternalFunctionItem_ ) )\ | |
14 | > ) | |
0bf4aa26 XL |
15 | > |
16 | > _ExternalStaticItem_ :\ | |
17 | > `static` `mut`<sup>?</sup> [IDENTIFIER] `:` [_Type_] `;` | |
18 | > | |
19 | > _ExternalFunctionItem_ :\ | |
20 | > `fn` [IDENTIFIER] [_Generics_]<sup>?</sup>\ | |
48663c56 | 21 | > `(` ( _NamedFunctionParameters_ | _NamedFunctionParametersWithVariadics_ )<sup>?</sup> `)`\ |
0bf4aa26 XL |
22 | > [_FunctionReturnType_]<sup>?</sup> [_WhereClause_]<sup>?</sup> `;` |
23 | > | |
24 | > _NamedFunctionParameters_ :\ | |
25 | > _NamedFunctionParam_ ( `,` _NamedFunctionParam_ )<sup>\*</sup> `,`<sup>?</sup> | |
26 | > | |
27 | > _NamedFunctionParam_ :\ | |
e74abb32 | 28 | > [_OuterAttribute_]<sup>\*</sup> ( [IDENTIFIER] | `_` ) `:` [_Type_] |
0bf4aa26 XL |
29 | > |
30 | > _NamedFunctionParametersWithVariadics_ :\ | |
e74abb32 | 31 | > ( _NamedFunctionParam_ `,` )<sup>\*</sup> _NamedFunctionParam_ `,` [_OuterAttribute_]<sup>\*</sup> `...` |
0bf4aa26 | 32 | |
e1599b0c XL |
33 | External blocks provide _declarations_ of items that are not _defined_ in the |
34 | current crate and are the basis of Rust's foreign function interface. These are | |
e74abb32 | 35 | akin to unchecked imports. |
e1599b0c XL |
36 | |
37 | Two kind of item _declarations_ are allowed in external blocks: [functions] and | |
38 | [statics]. Calling functions or accessing statics that are declared in external | |
39 | blocks is only allowed in an `unsafe` context. | |
ea8adc8c | 40 | |
29967ef6 XL |
41 | The `unsafe` keyword is syntactically allowed to appear before the `extern` |
42 | keyword, but it is rejected at a semantic level. This allows macros to consume | |
43 | the syntax and make use of the `unsafe` keyword, before removing it from the | |
44 | token stream. | |
45 | ||
dfeec247 XL |
46 | ## Functions |
47 | ||
ea8adc8c XL |
48 | Functions within external blocks are declared in the same way as other Rust |
49 | functions, with the exception that they may not have a body and are instead | |
0bf4aa26 XL |
50 | terminated by a semicolon. Patterns are not allowed in parameters, only |
51 | [IDENTIFIER] or `_` may be used. | |
ea8adc8c XL |
52 | |
53 | Functions within external blocks may be called by Rust code, just like | |
54 | functions defined in Rust. The Rust compiler automatically translates between | |
55 | the Rust ABI and the foreign ABI. | |
56 | ||
532ac7d7 XL |
57 | A function declared in an extern block is implicitly `unsafe`. When coerced to |
58 | a function pointer, a function declared in an extern block has type `unsafe | |
59 | extern "abi" for<'l1, ..., 'lm> fn(A1, ..., An) -> R`, where `'l1`, ... `'lm` | |
60 | are its lifetime parameters, `A1`, ..., `An` are the declared types of its | |
61 | parameters and `R` is the declared return type. | |
ea8adc8c | 62 | |
dfeec247 XL |
63 | ## Statics |
64 | ||
65 | Statics within external blocks are declared in the same way as [statics] outside of external blocks, | |
e1599b0c | 66 | except that they do not have an expression initializing their value. |
532ac7d7 | 67 | It is `unsafe` to access a static item declared in an extern block, whether or |
dfeec247 XL |
68 | not it's mutable, because there is nothing guaranteeing that the bit pattern at the static's |
69 | memory is valid for the type it is declared with, since some arbitrary (e.g. C) code is in charge | |
70 | of initializing the static. | |
71 | ||
72 | Extern statics can be either immutable or mutable just like [statics] outside of external blocks. | |
73 | An immutable static *must* be initialized before any Rust code is executed. It is not enough for | |
74 | the static to be initialized before Rust code reads from it. | |
ea8adc8c | 75 | |
532ac7d7 | 76 | ## ABI |
ea8adc8c | 77 | |
ea8adc8c XL |
78 | By default external blocks assume that the library they are calling uses the |
79 | standard C ABI on the specific platform. Other ABIs may be specified using an | |
80 | `abi` string, as shown here: | |
81 | ||
60c5eb7d | 82 | ```rust |
ea8adc8c XL |
83 | // Interface to the Windows API |
84 | extern "stdcall" { } | |
85 | ``` | |
86 | ||
87 | There are three ABI strings which are cross-platform, and which all compilers | |
88 | are guaranteed to support: | |
89 | ||
90 | * `extern "Rust"` -- The default ABI when you write a normal `fn foo()` in any | |
91 | Rust code. | |
92 | * `extern "C"` -- This is the same as `extern fn foo()`; whatever the default | |
93 | your C compiler supports. | |
94 | * `extern "system"` -- Usually the same as `extern "C"`, except on Win32, in | |
95 | which case it's `"stdcall"`, or what you should use to link to the Windows | |
96 | API itself | |
97 | ||
98 | There are also some platform-specific ABI strings: | |
99 | ||
100 | * `extern "cdecl"` -- The default for x86\_32 C code. | |
101 | * `extern "stdcall"` -- The default for the Win32 API on x86\_32. | |
102 | * `extern "win64"` -- The default for C code on x86\_64 Windows. | |
103 | * `extern "sysv64"` -- The default for C code on non-Windows x86\_64. | |
104 | * `extern "aapcs"` -- The default for ARM. | |
105 | * `extern "fastcall"` -- The `fastcall` ABI -- corresponds to MSVC's | |
106 | `__fastcall` and GCC and clang's `__attribute__((fastcall))` | |
107 | * `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's | |
108 | `__vectorcall` and clang's `__attribute__((vectorcall))` | |
109 | ||
532ac7d7 XL |
110 | ## Variadic functions |
111 | ||
112 | Functions within external blocks may be variadic by specifying `...` after one | |
113 | or more named arguments in the argument list: | |
ea8adc8c | 114 | |
60c5eb7d | 115 | ```rust |
532ac7d7 XL |
116 | extern { |
117 | fn foo(x: i32, ...); | |
118 | } | |
ea8adc8c XL |
119 | ``` |
120 | ||
532ac7d7 | 121 | ## Attributes on extern blocks |
13cf67c4 | 122 | |
532ac7d7 XL |
123 | The following [attributes] control the behavior of external blocks. |
124 | ||
125 | ### The `link` attribute | |
126 | ||
127 | The *`link` attribute* specifies the name of a native library that the | |
128 | compiler should link with for the items within an `extern` block. It uses the | |
129 | [_MetaListNameValueStr_] syntax to specify its inputs. The `name` key is the | |
130 | name of the native library to link. The `kind` key is an optional value which | |
131 | specifies the kind of library with the following possible values: | |
132 | ||
133 | - `dylib` — Indicates a dynamic library. This is the default if `kind` is not | |
134 | specified. | |
135 | - `static` — Indicates a static library. | |
136 | - `framework` — Indicates a macOS framework. This is only valid for macOS | |
137 | targets. | |
138 | ||
139 | The `name` key must be included if `kind` is specified. | |
140 | ||
141 | The `wasm_import_module` key may be used to specify the [WebAssembly module] | |
142 | name for the items within an `extern` block when importing symbols from the | |
143 | host environment. The default module name is `env` if `wasm_import_module` is | |
144 | not specified. | |
145 | ||
60c5eb7d | 146 | <!-- ignore: requires extern linking --> |
532ac7d7 XL |
147 | ```rust,ignore |
148 | #[link(name = "crypto")] | |
149 | extern { | |
150 | // … | |
151 | } | |
152 | ||
153 | #[link(name = "CoreFoundation", kind = "framework")] | |
154 | extern { | |
155 | // … | |
156 | } | |
157 | ||
158 | #[link(wasm_import_module = "foo")] | |
159 | extern { | |
160 | // … | |
161 | } | |
162 | ``` | |
ea8adc8c XL |
163 | |
164 | It is valid to add the `link` attribute on an empty extern block. You can use | |
165 | this to satisfy the linking requirements of extern blocks elsewhere in your | |
166 | code (including upstream crates) instead of adding the attribute to each extern | |
167 | block. | |
0bf4aa26 | 168 | |
532ac7d7 XL |
169 | ### The `link_name` attribute |
170 | ||
171 | The `link_name` attribute may be specified on declarations inside an `extern` | |
172 | block to indicate the symbol to import for the given function or static. It | |
173 | uses the [_MetaNameValueStr_] syntax to specify the name of the symbol. | |
174 | ||
60c5eb7d | 175 | ```rust |
532ac7d7 XL |
176 | extern { |
177 | #[link_name = "actual_symbol_name"] | |
178 | fn name_in_rust(); | |
179 | } | |
180 | ``` | |
181 | ||
e74abb32 XL |
182 | ### Attributes on function parameters |
183 | ||
184 | Attributes on extern function parameters follow the same rules and | |
185 | restrictions as [regular function parameters]. | |
186 | ||
416331ca | 187 | [IDENTIFIER]: ../identifiers.md |
532ac7d7 | 188 | [WebAssembly module]: https://webassembly.github.io/spec/core/syntax/modules.html |
e1599b0c XL |
189 | [functions]: functions.md |
190 | [statics]: static-items.md | |
416331ca XL |
191 | [_Abi_]: functions.md |
192 | [_FunctionReturnType_]: functions.md | |
193 | [_Generics_]: generics.md | |
194 | [_InnerAttribute_]: ../attributes.md | |
e74abb32 | 195 | [_MacroInvocationSemi_]: ../macros.md#macro-invocation |
416331ca XL |
196 | [_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax |
197 | [_MetaNameValueStr_]: ../attributes.md#meta-item-attribute-syntax | |
198 | [_OuterAttribute_]: ../attributes.md | |
199 | [_Type_]: ../types.md#type-expressions | |
200 | [_Visibility_]: ../visibility-and-privacy.md | |
201 | [_WhereClause_]: generics.md#where-clauses | |
202 | [attributes]: ../attributes.md | |
60c5eb7d | 203 | [regular function parameters]: functions.md#attributes-on-function-parameters |