1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
//! Configure how `cheadergen` generates C/C++ headers from Rust.
//!
//! `cheadergen` generates C/C++ header files from Rust libraries that expose a
//! `pub extern "C"` API. Output is controlled in two complementary ways:
//!
//! - **[`cheadergen.toml`](config_reference)** — a project-wide TOML file that
//! the CLI loads via `--config`. It sets the preamble, include guards, sort
//! order, per-package opaque/skip rules, per-header overrides, and
//! language-specific options. See the [config reference](config_reference)
//! for the full schema.
//! - **Per-item attributes** — `#[cheadergen::config(...)]` on items and
//! `#[cheadergen(...)]` on fields and variants, placed in your Rust source
//! to control how an individual definition appears in the generated header.
//! See the [`config`] macro for the directive reference.
//!
//! # Per-item attributes
//!
//! There are two attribute levels:
//!
//! - [`#[cheadergen::config(...)]`](config) — placed on items (structs, enums,
//! unions, functions, statics, type aliases) to control their header
//! representation.
//! - `#[cheadergen(...)]` — placed on fields and enum variants to control
//! their individual representation within a parent item.
//!
//! ## Example
//!
//! ```ignore
//! #[cheadergen::config(export, rename = "CColor")]
//! #[repr(C)]
//! pub enum Color {
//! #[cheadergen(rename = "COLOR_RED")]
//! Red,
//! Green,
//! Blue,
//! }
//!
//! #[cheadergen::config(export, field_names(x, y))]
//! #[repr(C)]
//! pub struct Point2D(pub f64, pub f64);
//!
//! #[cheadergen::config(skip)]
//! #[unsafe(no_mangle)]
//! pub extern "C" fn internal_helper() {}
//! ```
/// Control how a Rust item appears in the generated C/C++ header.
///
/// # Example
///
/// ```ignore
/// #[cheadergen::config(export, rename = "CConfig")]
/// // ~~~~~~ ~~~~~~~~~~~~~~~~~~
/// // │ └ Override the C name
/// // └ Force inclusion in the header
/// #[repr(C)]
/// pub struct Config {
/// #[cheadergen(rename = "raw_width")]
/// // ~~~~~~~~~~~~~~~~~~~~
/// // └ Override the C field name
/// pub width: u32,
/// #[cheadergen(bitfield = 8)]
/// // ~~~~~~~~~~~
/// // └ Emit as a C bitfield with width 8
/// pub flags: u8,
/// #[cheadergen(const_ptr)]
/// // ~~~~~~~~~
/// // └ Emit a pointer field as a constant pointer
/// pub data: std::ptr::NonNull<u8>,
/// }
/// ```
///
/// # Directives
///
/// | Name | Applies to | Required |
/// |------|-----------|----------|
/// | [`export`](#export) | struct, enum, union, type alias | No |
/// | [`opaque`](#opaque) | struct, enum, union, type alias | No |
/// | [`skip`](#skip) | struct, enum, union, type alias, function, static | No |
/// | [`rename`](#rename) | struct, enum, union, type alias, function, static | No |
/// | [`prefix_with_name`](#prefix_with_name) | enum | No |
/// | [`field_names`](#field_names) | tuple struct | No |
/// | [`rename_all`](#rename_all) | struct, enum, union | No |
/// | [`rename_all_fields`](#rename_all_fields) | enum (with struct variant) | No |
///
/// ## `export`
///
/// Force the item to be included in the generated header. By default, `cheadergen` only includes
/// items that are reachable from `pub extern "C"` functions. Use `export` to include items that
/// are not directly reachable but should still appear in the header.
///
/// ```ignore
/// #[cheadergen::config(export)]
/// // ~~~~~~
/// // └ Include this struct in the header
/// #[repr(C)]
/// pub struct Config {
/// pub width: u32,
/// }
/// ```
///
/// Combine with [`opaque`](#opaque) to force inclusion as a forward declaration
/// without exposing the layout:
///
/// ```ignore
/// #[cheadergen::config(export, opaque)]
/// // ~~~~~~~~~~~~~~
/// // └ Force-include as an opaque (forward-declared) type
/// pub struct OpaqueHandle {
/// _inner: u64,
/// }
/// ```
///
/// Cannot be applied to functions or statics (they are included via `#[unsafe(no_mangle)]`).
/// Cannot be combined with [`skip`](#skip).
///
/// ## `opaque`
///
/// Emit the type as an opaque forward declaration whenever it appears in the
/// generated header — i.e. without exposing its fields or variants. On its own,
/// `opaque` is a hint: it does not force inclusion. The type is still subject
/// to the usual reachability rules and `skip` overrides.
///
/// ```ignore
/// #[cheadergen::config(opaque)]
/// // ~~~~~~
/// // └ If included, emit as a forward declaration
/// pub struct InternalHandle {
/// _inner: u64,
/// }
/// ```
///
/// Combine with [`export`](#export) to force inclusion as an opaque
/// forward declaration regardless of reachability.
///
/// Cannot be applied to functions, statics, or constants — opaque only makes
/// sense for types.
///
/// ## `skip`
///
/// Exclude the item from the generated header, even if it would otherwise be included.
///
/// ```ignore
/// #[cheadergen::config(skip)]
/// // ~~~~
/// // └ Exclude this function from the header
/// #[unsafe(no_mangle)]
/// pub extern "C" fn internal_helper() {}
/// ```
///
/// Cannot be combined with [`export`](#export).
///
/// ## `rename`
///
/// Override the C name of the item. By default, the Rust identifier is used as-is.
///
/// ```ignore
/// #[cheadergen::config(rename = "CPoint")]
/// // ~~~~~~~~~~~~~~~~~
/// // └ Use "CPoint" instead of "Point" in the header
/// #[repr(C)]
/// pub struct Point {
/// pub x: f64,
/// pub y: f64,
/// }
/// ```
///
/// ## `prefix_with_name`
///
/// Prefix each variant of a C enum with the enum's name, separated by an underscore.
/// This is common in C to avoid name collisions since C enums share a global namespace.
///
/// ```ignore
/// #[cheadergen::config(prefix_with_name)]
/// // ~~~~~~~~~~~~~~~~
/// // └ Variants become Status_Ok, Status_Error, ...
/// #[repr(C)]
/// pub enum Status {
/// Ok,
/// Error,
/// }
/// ```
///
/// Use `prefix_with_name = false` to explicitly disable the behavior (useful when overriding
/// a default configuration).
///
/// Can only be applied to enums.
///
/// ## `field_names`
///
/// Assign C field names to the fields of a tuple struct. The number of names must match
/// the number of fields.
///
/// ```ignore
/// #[cheadergen::config(field_names(x, y))]
/// // ~~~~~~~~~~~~~~~~~
/// // └ Name the two fields "x" and "y" in the C header
/// #[repr(C)]
/// pub struct Point2D(pub f64, pub f64);
/// ```
///
/// Can only be applied to tuple structs.
///
/// ## `rename_all`
///
/// Bulk-rename fields (struct/union) or variants (enum) using a casing rule. Mirrors serde's
/// directive of the same name. Accepted values (string literal, case-sensitive):
///
/// | Rule | Example: `max_value` / `MaxValue` becomes |
/// |---------------------------|--------------------------------------------|
/// | `"camelCase"` | `maxValue` |
/// | `"PascalCase"` | `MaxValue` |
/// | `"snake_case"` | `max_value` |
/// | `"SCREAMING_SNAKE_CASE"` | `MAX_VALUE` |
///
/// ```ignore
/// #[cheadergen::config(export, rename_all = "camelCase")]
/// // ~~~~~~~~~~~~~~~~~~~~~~~~
/// // └ Fields become maxValue, minValue
/// #[repr(C)]
/// pub struct Settings {
/// pub max_value: u32,
/// pub min_value: u32,
/// }
/// ```
///
/// A per-field/per-variant `#[cheadergen(rename = "...")]` always wins over the bulk rule.
///
/// When combined with [`prefix_with_name`](#prefix_with_name), the prefix (derived from the
/// enum name) is also cased so the resulting C identifier is consistent:
///
/// ```ignore
/// #[cheadergen::config(export, prefix_with_name, rename_all = "SCREAMING_SNAKE_CASE")]
/// #[repr(C)]
/// pub enum MyStatus {
/// OkResult,
/// ErrorCode,
/// }
/// // Variants emitted as `MY_STATUS_OK_RESULT`, `MY_STATUS_ERROR_CODE`.
/// ```
///
/// An explicit `rename = "..."` on the enum short-circuits the prefix casing — the explicit
/// C name is used verbatim as the prefix.
///
/// Cannot be applied to functions, statics, or type aliases.
///
/// ## `rename_all_fields`
///
/// On an enum, bulk-rename the fields inside every struct variant. Accepts the same casing
/// values as [`rename_all`](#rename_all). Variant names themselves are unaffected (use
/// `rename_all` for those).
///
/// ```ignore
/// #[cheadergen::config(export, rename_all_fields = "camelCase")]
/// // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // └ Struct-variant fields become camelCase
/// #[repr(C)]
/// pub enum Message {
/// Plain,
/// WithBody {
/// message_text: u32, // -> messageText
/// sender_id: u32, // -> senderId
/// },
/// }
/// ```
///
/// Can only be applied to enums that have at least one struct (named-fields) variant.
///
/// # Field and variant directives
///
/// Fields and enum variants use `#[cheadergen(...)]` (without `::config`).
///
/// | Name | Applies to | Required |
/// |------|-----------|----------|
/// | [`rename`](#field-rename) | field, variant | No |
/// | [`bitfield`](#bitfield) | field (not variant) | No |
/// | [`const_ptr`](#const_ptr) | field (not variant) | No |
///
/// ## `rename` (field) {#field-rename}
///
/// Override the C name of a struct field or enum variant.
///
/// ```ignore
/// #[cheadergen::config(export)]
/// #[repr(C)]
/// pub enum Color {
/// #[cheadergen(rename = "COLOR_RED")]
/// // ~~~~~~~~~~~~~~~~~~~~
/// // └ Use "COLOR_RED" instead of "Red"
/// Red,
/// Green,
/// }
/// ```
///
/// ## `bitfield`
///
/// Emit the field as a C bitfield with the given width in bits.
///
/// ```ignore
/// #[cheadergen::config(export)]
/// #[repr(C)]
/// pub struct Flags {
/// #[cheadergen(bitfield = 4)]
/// // ~~~~~~~~~~~
/// // └ Emit as a 4-bit bitfield
/// pub mode: u8,
/// }
/// ```
///
/// Cannot be applied to enum variants.
///
/// ## `const_ptr`
///
/// Qualify a pointer field as a constant pointer in the generated C header.
/// This is useful for Rust field types like `NonNull<T>`, which normally lower
/// to `T *` but may need to be exposed as `const T *` to C consumers.
///
/// ```ignore
/// use std::ptr::NonNull;
///
/// #[cheadergen::config(export)]
/// #[repr(C)]
/// pub struct View {
/// #[cheadergen(const_ptr)]
/// // ~~~~~~~~~
/// // └ Emit as `const uint8_t *data`
/// pub data: NonNull<u8>,
/// }
/// ```
///
/// The directive is checked after type simplification. If the field does not
/// resolve to a pointer type in C, header generation fails.
///
/// Cannot be applied to enum variants.
pub use config;