Skip to content

Commit 046ddcb

Browse files
authored
Several tidyings in the C bindings (#885)
* Several tidyings in the C bindings - Add several comments to the C bindings output - Move the `#include <stdlib.h>` out of the `.h` file and into the `.c` file, since it's for `realloc`/`free` etc. and those are only used in the `.c` file. - Use named structs inside of typedefs, so that the structs have names in the generated debug info. * Fix `<stdlib.h>` for the Go bindings. * Fix a stray backslash. * Ensure that <uchar.h> is included in the header file when needed. * Remove `__used__` attributes. * Re-add `__weak__`.
1 parent b6c9de7 commit 046ddcb

File tree

5 files changed

+63
-40
lines changed

5 files changed

+63
-40
lines changed

crates/c/src/lib.rs

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ use wit_component::StringEncoding;
1616
struct C {
1717
src: Source,
1818
opts: Opts,
19-
includes: Vec<String>,
19+
h_includes: Vec<String>,
20+
c_includes: Vec<String>,
2021
return_pointer_area_size: usize,
2122
return_pointer_area_align: usize,
2223
names: Ns,
@@ -181,6 +182,7 @@ impl WorldGenerator for C {
181182
if i == 0 {
182183
let name = resolve.name_world_key(name);
183184
uwriteln!(gen.src.h_fns, "\n// Imported Functions from `{name}`");
185+
uwriteln!(gen.src.c_fns, "\n// Imported Functions from `{name}`");
184186
}
185187
gen.import(Some(name), func);
186188
}
@@ -202,6 +204,7 @@ impl WorldGenerator for C {
202204
for (i, (_name, func)) in funcs.iter().enumerate() {
203205
if i == 0 {
204206
uwriteln!(gen.src.h_fns, "\n// Imported Functions from `{name}`");
207+
uwriteln!(gen.src.c_fns, "\n// Imported Functions from `{name}`");
205208
}
206209
gen.import(None, func);
207210
}
@@ -224,6 +227,7 @@ impl WorldGenerator for C {
224227
if i == 0 {
225228
let name = resolve.name_world_key(name);
226229
uwriteln!(gen.src.h_fns, "\n// Exported Functions from `{name}`");
230+
uwriteln!(gen.src.c_fns, "\n// Exported Functions from `{name}`");
227231
}
228232
gen.export(func, Some(name));
229233
}
@@ -246,6 +250,7 @@ impl WorldGenerator for C {
246250
for (i, (_name, func)) in funcs.iter().enumerate() {
247251
if i == 0 {
248252
uwriteln!(gen.src.h_fns, "\n// Exported Functions from `{name}`");
253+
uwriteln!(gen.src.c_fns, "\n// Exported Functions from `{name}`");
249254
}
250255
gen.export(func, None);
251256
}
@@ -272,8 +277,12 @@ impl WorldGenerator for C {
272277

273278
fn finish(&mut self, resolve: &Resolve, id: WorldId, files: &mut Files) -> Result<()> {
274279
let linking_symbol = component_type_object::linking_symbol(&self.world);
275-
self.include("<stdlib.h>");
280+
self.c_include("<stdlib.h>");
276281
let snake = self.world.to_snake_case();
282+
uwriteln!(
283+
self.src.c_adapters,
284+
"\n// Ensure that the *_component_type.o object is linked in"
285+
);
277286
uwrite!(
278287
self.src.c_adapters,
279288
"
@@ -287,11 +296,11 @@ impl WorldGenerator for C {
287296
self.print_intrinsics();
288297

289298
if self.needs_string {
290-
self.include("<string.h>");
299+
self.c_include("<string.h>");
291300
let (strlen, size) = match self.opts.string_encoding {
292301
StringEncoding::UTF8 => (format!("strlen(s)"), 1),
293302
StringEncoding::UTF16 => {
294-
self.include("<uchar.h>");
303+
self.h_include("<uchar.h>");
295304
uwrite!(
296305
self.src.h_helpers,
297306
"
@@ -375,18 +384,17 @@ impl WorldGenerator for C {
375384
h_str.deindent(1);
376385
uwriteln!(h_str, "\n#endif\n");
377386

378-
self.include("<stdint.h>");
379-
self.include("<stdbool.h>");
380-
381-
for include in self.includes.iter() {
387+
uwriteln!(h_str, "#include <stdint.h>");
388+
uwriteln!(h_str, "#include <stdbool.h>");
389+
for include in self.h_includes.iter() {
382390
uwriteln!(h_str, "#include {include}");
383391
}
384392

385393
let mut c_str = wit_bindgen_core::Source::default();
386394
wit_bindgen_core::generated_preamble(&mut c_str, version);
387395
uwriteln!(c_str, "#include \"{snake}.h\"");
388-
if c_str.len() > 0 {
389-
c_str.push_str("\n");
396+
for include in self.c_includes.iter() {
397+
uwriteln!(c_str, "#include {include}");
390398
}
391399
c_str.push_str(&self.src.c_defs);
392400
c_str.push_str(&self.src.c_fns);
@@ -395,7 +403,7 @@ impl WorldGenerator for C {
395403
uwriteln!(
396404
h_str,
397405
"
398-
typedef struct {{\n\
406+
typedef struct {snake}_string_t {{\n\
399407
{ty} *ptr;\n\
400408
size_t len;\n\
401409
}} {snake}_string_t;",
@@ -490,8 +498,12 @@ impl C {
490498
}
491499
}
492500

493-
fn include(&mut self, s: &str) {
494-
self.includes.push(s.to_string());
501+
fn h_include(&mut self, s: &str) {
502+
self.h_includes.push(s.to_string());
503+
}
504+
505+
fn c_include(&mut self, s: &str) {
506+
self.c_includes.push(s.to_string());
495507
}
496508

497509
fn char_type(&self) -> &'static str {
@@ -825,6 +837,8 @@ impl C {
825837
fn print_intrinsics(&mut self) {
826838
// Note that these intrinsics are declared as `weak` so they can be
827839
// overridden from some other symbol.
840+
self.src.c_fns("\n// Canonical ABI intrinsics");
841+
self.src.c_fns("\n");
828842
self.src.c_fns(
829843
r#"
830844
__attribute__((__weak__, __export_name__("cabi_realloc")))
@@ -918,16 +932,15 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
918932
fn type_record(&mut self, id: TypeId, _name: &str, record: &Record, docs: &Docs) {
919933
self.src.h_defs("\n");
920934
self.docs(docs, SourceType::HDefs);
921-
self.src.h_defs("typedef struct {\n");
935+
self.start_typedef_struct(id);
922936
for field in record.fields.iter() {
923937
self.docs(&field.docs, SourceType::HDefs);
924938
self.print_ty(SourceType::HDefs, &field.ty);
925939
self.src.h_defs(" ");
926940
self.src.h_defs(&to_c_ident(&field.name));
927941
self.src.h_defs(";\n");
928942
}
929-
self.src.h_defs("} ");
930-
self.print_typedef_target(id);
943+
self.finish_typedef_struct(id);
931944
}
932945

933946
fn type_resource(&mut self, id: TypeId, name: &str, _docs: &Docs) {
@@ -1097,13 +1110,12 @@ void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
10971110
fn type_tuple(&mut self, id: TypeId, _name: &str, tuple: &Tuple, docs: &Docs) {
10981111
self.src.h_defs("\n");
10991112
self.docs(docs, SourceType::HDefs);
1100-
self.src.h_defs("typedef struct {\n");
1113+
self.start_typedef_struct(id);
11011114
for (i, ty) in tuple.types.iter().enumerate() {
11021115
self.print_ty(SourceType::HDefs, ty);
11031116
uwriteln!(self.src.h_defs, " f{i};");
11041117
}
1105-
self.src.h_defs("} ");
1106-
self.print_typedef_target(id);
1118+
self.finish_typedef_struct(id);
11071119
}
11081120

11091121
fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
@@ -1133,7 +1145,7 @@ void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
11331145
fn type_variant(&mut self, id: TypeId, name: &str, variant: &Variant, docs: &Docs) {
11341146
self.src.h_defs("\n");
11351147
self.docs(docs, SourceType::HDefs);
1136-
self.src.h_defs("typedef struct {\n");
1148+
self.start_typedef_struct(id);
11371149
self.src.h_defs(int_repr(variant.tag()));
11381150
self.src.h_defs(" tag;\n");
11391151

@@ -1154,8 +1166,7 @@ void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
11541166
}
11551167
self.src.h_defs("} val;\n");
11561168
}
1157-
self.src.h_defs("} ");
1158-
self.print_typedef_target(id);
1169+
self.finish_typedef_struct(id);
11591170

11601171
if variant.cases.len() > 0 {
11611172
self.src.h_defs("\n");
@@ -1175,18 +1186,17 @@ void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
11751186
fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) {
11761187
self.src.h_defs("\n");
11771188
self.docs(docs, SourceType::HDefs);
1178-
self.src.h_defs("typedef struct {\n");
1189+
self.start_typedef_struct(id);
11791190
self.src.h_defs("bool is_some;\n");
11801191
self.print_ty(SourceType::HDefs, payload);
11811192
self.src.h_defs(" val;\n");
1182-
self.src.h_defs("} ");
1183-
self.print_typedef_target(id);
1193+
self.finish_typedef_struct(id);
11841194
}
11851195

11861196
fn type_result(&mut self, id: TypeId, _name: &str, result: &Result_, docs: &Docs) {
11871197
self.src.h_defs("\n");
11881198
self.docs(docs, SourceType::HDefs);
1189-
self.src.h_defs("typedef struct {\n");
1199+
self.start_typedef_struct(id);
11901200
self.src.h_defs("bool is_err;\n");
11911201
if result.ok.is_some() || result.err.is_some() {
11921202
self.src.h_defs("union {\n");
@@ -1200,8 +1210,7 @@ void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
12001210
}
12011211
self.src.h_defs("} val;\n");
12021212
}
1203-
self.src.h_defs("} ");
1204-
self.print_typedef_target(id);
1213+
self.finish_typedef_struct(id);
12051214
}
12061215

12071216
fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
@@ -1246,12 +1255,11 @@ void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
12461255
fn type_list(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
12471256
self.src.h_defs("\n");
12481257
self.docs(docs, SourceType::HDefs);
1249-
self.src.h_defs("typedef struct {\n");
1258+
self.start_typedef_struct(id);
12501259
self.print_ty(SourceType::HDefs, ty);
12511260
self.src.h_defs(" *ptr;\n");
12521261
self.src.h_defs("size_t len;\n");
1253-
self.src.h_defs("} ");
1254-
self.print_typedef_target(id);
1262+
self.finish_typedef_struct(id);
12551263
}
12561264

12571265
fn type_builtin(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs) {
@@ -1353,6 +1361,7 @@ impl InterfaceGenerator<'_> {
13531361
}
13541362

13551363
self.src.h_defs("\ntypedef ");
1364+
let name = &self.gen.type_names[&ty];
13561365
match kind {
13571366
TypeDefKind::Type(_)
13581367
| TypeDefKind::Flags(_)
@@ -1373,26 +1382,23 @@ impl InterfaceGenerator<'_> {
13731382
}
13741383
}
13751384
TypeDefKind::Tuple(t) => {
1376-
self.src.h_defs("struct {\n");
1385+
self.src.h_defs(&format!("struct {name} {{\n"));
13771386
for (i, t) in t.types.iter().enumerate() {
13781387
let ty = self.gen.type_name(t);
13791388
uwriteln!(self.src.h_defs, "{ty} f{i};");
13801389
}
13811390
self.src.h_defs("}");
13821391
}
13831392
TypeDefKind::Option(t) => {
1384-
self.src.h_defs("struct {\n");
1393+
self.src.h_defs(&format!("struct {name} {{\n"));
13851394
self.src.h_defs("bool is_some;\n");
13861395
let ty = self.gen.type_name(t);
13871396
uwriteln!(self.src.h_defs, "{ty} val;");
13881397
self.src.h_defs("}");
13891398
}
13901399
TypeDefKind::Result(r) => {
1391-
self.src.h_defs(
1392-
"struct {
1393-
bool is_err;
1394-
",
1395-
);
1400+
self.src.h_defs(&format!("struct {name} {{\n"));
1401+
self.src.h_defs("bool is_err;\n");
13961402
let ok_ty = r.ok.as_ref();
13971403
let err_ty = r.err.as_ref();
13981404
if ok_ty.is_some() || err_ty.is_some() {
@@ -1410,7 +1416,7 @@ impl InterfaceGenerator<'_> {
14101416
self.src.h_defs("}");
14111417
}
14121418
TypeDefKind::List(t) => {
1413-
self.src.h_defs("struct {\n");
1419+
self.src.h_defs(&format!("struct {name} {{\n"));
14141420
let ty = self.gen.type_name(t);
14151421
uwriteln!(self.src.h_defs, "{ty} *ptr;");
14161422
self.src.h_defs("size_t len;\n");
@@ -1672,6 +1678,8 @@ impl InterfaceGenerator<'_> {
16721678
fn export(&mut self, func: &Function, interface_name: Option<&WorldKey>) {
16731679
let sig = self.resolve.wasm_signature(AbiVariant::GuestExport, func);
16741680

1681+
self.src.c_fns("\n");
1682+
16751683
let core_module_name = interface_name.map(|s| self.resolve.name_world_key(s));
16761684
let export_name = func.core_export_name(core_module_name.as_deref());
16771685

@@ -1879,6 +1887,18 @@ impl InterfaceGenerator<'_> {
18791887
self.src.h_defs(";\n");
18801888
}
18811889

1890+
fn start_typedef_struct(&mut self, id: TypeId) {
1891+
let name = &self.gen.type_names[&id];
1892+
self.src.h_defs("typedef struct ");
1893+
self.src.h_defs(&name);
1894+
self.src.h_defs(" {\n");
1895+
}
1896+
1897+
fn finish_typedef_struct(&mut self, id: TypeId) {
1898+
self.src.h_defs("} ");
1899+
self.print_typedef_target(id);
1900+
}
1901+
18821902
fn owner_namespace(&self, id: TypeId) -> String {
18831903
owner_namespace(
18841904
self.interface,

crates/go/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ impl WorldGenerator for TinyGo {
304304
self.src.push_str("// #include \"");
305305
self.src.push_str(self.world.to_snake_case().as_str());
306306
self.src.push_str(".h\"\n");
307+
self.src.push_str("// #include <stdlib.h>\n");
307308
if self.preamble.len() > 0 {
308309
self.src.append_src(&self.preamble);
309310
}

tests/runtime/resource_import_and_export/wasm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/* #include <limits.h> */
55
/* #include <math.h> */
66
/* #include <stdalign.h> */
7-
/* #include <stdlib.h> */
7+
#include <stdlib.h>
88
#include <string.h>
99

1010
struct exports_test_resource_import_and_export_test_thing_t {

tests/runtime/resources/wasm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <limits.h>
33
#include <math.h>
44
#include <resources.h>
5+
#include <stdlib.h>
56

67
struct exports_x_t {
78
int32_t a;

tests/runtime/variants/wasm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <assert.h>
22
#include <variants.h>
3+
#include <stddef.h>
34

45
void variants_test_imports() {
56
{

0 commit comments

Comments
 (0)