From f5ce5b4869b31632e7229b7650b97d6d6d418286 Mon Sep 17 00:00:00 2001 From: Alan George Date: Mon, 14 Sep 2026 18:02:21 -0600 Subject: [PATCH 1/6] Update C++ bindings for UniFFI 0.31 --- Cargo.lock | 193 +++++++++++++----- Cargo.toml | 4 +- README.md | 6 + bindgen/Cargo.toml | 4 +- bindgen/src/bindings/cpp/gen_cpp/compounds.rs | 5 +- bindgen/src/bindings/cpp/gen_cpp/enum_.rs | 2 +- .../src/bindings/cpp/gen_cpp/filters/mod.rs | 14 +- .../src/bindings/cpp/gen_cpp/miscellany.rs | 2 +- bindgen/src/bindings/cpp/gen_cpp/object.rs | 5 +- .../src/bindings/cpp/gen_cpp/primitives.rs | 5 +- bindgen/src/bindings/cpp/gen_cpp/record.rs | 2 +- bindgen/src/bindings/cpp/mod.rs | 13 +- .../src/bindings/cpp/templates/callback.hpp | 4 +- .../cpp/templates/callback_iface_tmpl.cpp | 6 + bindgen/src/bindings/cpp/templates/enum.hpp | 2 +- .../src/bindings/cpp/templates/enum_tmpl.cpp | 6 +- .../src/bindings/cpp/templates/handle_map.cpp | 5 +- bindgen/src/bindings/cpp/templates/obj.cpp | 16 +- bindgen/src/bindings/cpp/templates/obj.hpp | 17 +- .../src/bindings/cpp/templates/obj_conv.cpp | 27 ++- .../src/bindings/cpp/templates/obj_conv.hpp | 4 +- .../cpp/templates/scaffolding/macros.cpp | 8 + .../cpp/templates/scaffolding/obj.cpp | 15 +- .../cpp/templates/scaffolding/obj.hpp | 4 +- .../src/bindings/cpp/templates/wrapper.cpp | 2 + .../src/bindings/cpp/templates/wrapper.hpp | 2 + cpp-tests/tests/coverall/main.cpp | 2 +- fixtures/Cargo.toml | 26 +-- fixtures/ext-types-export/src/lib.rs | 2 + 29 files changed, 287 insertions(+), 116 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 565c65f..d7cc9de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,7 +62,20 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7" dependencies = [ - "askama_derive", + "askama_derive 0.13.1", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" +dependencies = [ + "askama_derive 0.14.0", "itoa", "percent-encoding", "serde", @@ -75,7 +88,24 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac" dependencies = [ - "askama_parser", + "askama_parser 0.13.0", + "basic-toml", + "memchr", + "proc-macro2", + "quote", + "rustc-hash", + "serde", + "serde_derive", + "syn", +] + +[[package]] +name = "askama_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" +dependencies = [ + "askama_parser 0.14.0", "basic-toml", "memchr", "proc-macro2", @@ -95,7 +125,19 @@ dependencies = [ "memchr", "serde", "serde_derive", - "winnow", + "winnow 0.7.13", +] + +[[package]] +name = "askama_parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" +dependencies = [ + "memchr", + "serde", + "serde_derive", + "winnow 0.7.13", ] [[package]] @@ -311,6 +353,8 @@ checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", "hashbrown", + "serde", + "serde_core", ] [[package]] @@ -507,11 +551,20 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_spanned" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" +dependencies = [ + "serde_core", +] + [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "smawk" @@ -622,13 +675,43 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.5.11" +version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "serde", + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow 0.7.13", ] +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow 1.0.4", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + [[package]] name = "topological-sort" version = "0.2.2" @@ -670,8 +753,8 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" -version = "0.29.4" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +version = "0.31.2" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "anyhow", "cargo_metadata", @@ -684,10 +767,10 @@ dependencies = [ [[package]] name = "uniffi-bindgen-cpp" -version = "0.9.0+v0.29.4" +version = "0.10.0+v0.31.2" dependencies = [ "anyhow", - "askama", + "askama 0.13.1", "camino", "cargo_metadata", "clap", @@ -763,25 +846,25 @@ dependencies = [ [[package]] name = "uniffi-example-arithmetic" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ - "thiserror 1.0.50", + "thiserror 2.0.16", "uniffi", ] [[package]] name = "uniffi-example-callbacks" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ - "thiserror 1.0.50", + "thiserror 2.0.16", "uniffi", ] [[package]] name = "uniffi-example-custom-types" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "anyhow", "bytes", @@ -792,7 +875,7 @@ dependencies = [ [[package]] name = "uniffi-example-geometry" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "uniffi", ] @@ -800,7 +883,7 @@ dependencies = [ [[package]] name = "uniffi-example-rondpoint" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "uniffi", ] @@ -808,7 +891,7 @@ dependencies = [ [[package]] name = "uniffi-example-sprites" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "uniffi", ] @@ -816,19 +899,19 @@ dependencies = [ [[package]] name = "uniffi-example-todolist" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "once_cell", - "thiserror 1.0.50", + "thiserror 2.0.16", "uniffi", ] [[package]] name = "uniffi-example-traits" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ - "thiserror 1.0.50", + "thiserror 2.0.16", "uniffi", ] @@ -850,48 +933,48 @@ dependencies = [ [[package]] name = "uniffi-fixture-callbacks" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ - "thiserror 1.0.50", + "thiserror 2.0.16", "uniffi", ] [[package]] name = "uniffi-fixture-coverall" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "once_cell", - "thiserror 1.0.50", + "thiserror 2.0.16", "uniffi", ] [[package]] name = "uniffi-fixture-docstring" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ - "thiserror 1.0.50", + "thiserror 2.0.16", "uniffi", ] [[package]] name = "uniffi-fixture-time" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "chrono", - "thiserror 1.0.50", + "thiserror 2.0.16", "uniffi", ] [[package]] name = "uniffi-fixture-trait-methods" version = "0.22.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "once_cell", - "thiserror 1.0.50", + "thiserror 2.0.16", "uniffi", ] @@ -911,11 +994,11 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.29.4" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +version = "0.31.2" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "anyhow", - "askama", + "askama 0.14.0", "camino", "cargo_metadata", "fs-err", @@ -936,8 +1019,8 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.29.4" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +version = "0.31.2" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "anyhow", "camino", @@ -946,8 +1029,8 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.29.4" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +version = "0.31.2" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "anyhow", "bytes", @@ -957,8 +1040,8 @@ dependencies = [ [[package]] name = "uniffi_internal_macros" -version = "0.29.4" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +version = "0.31.2" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "anyhow", "indexmap", @@ -969,8 +1052,8 @@ dependencies = [ [[package]] name = "uniffi_macros" -version = "0.29.4" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +version = "0.31.2" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "camino", "fs-err", @@ -985,8 +1068,8 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.29.4" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +version = "0.31.2" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "anyhow", "siphasher", @@ -996,8 +1079,8 @@ dependencies = [ [[package]] name = "uniffi_pipeline" -version = "0.29.4" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +version = "0.31.2" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "anyhow", "heck 0.5.0", @@ -1008,8 +1091,8 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.29.4" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +version = "0.31.2" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "anyhow", "textwrap", @@ -1037,7 +1120,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "weedle2" version = "5.0.0" -source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.29.4#00cd7e313cf73c78637161831ff17f8f53f7b824" +source = "git+https://github.com/mozilla/uniffi-rs.git?tag=v0.31.2#05b45b110f652d58d94c653992aeb3adc3a094f4" dependencies = [ "nom", ] @@ -1213,3 +1296,9 @@ checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" diff --git a/Cargo.toml b/Cargo.toml index 06da37f..6f7a295 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,5 @@ members = ["bindgen", "fixtures"] resolver = "2" [workspace.dependencies] -uniffi = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4", features = ["cargo-metadata"] } +uniffi = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2", features = ["cargo-metadata"] } diff --git a/README.md b/README.md index b8d8ee5..bc06eef 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,12 @@ Newer Rust versions should also work fine. cargo install uniffi-bindgen-cpp --git https://github.com/NordSecurity/uniffi-bindgen-cpp --tag v0.8.1+v0.29.4 ``` +For this UniFFI 0.31 development branch, install directly from the checkout: + +```bash +cargo install --path bindgen +``` + # How to generate bindings ## Generating with a single UDL file diff --git a/bindgen/Cargo.toml b/bindgen/Cargo.toml index 468c458..7e4673e 100644 --- a/bindgen/Cargo.toml +++ b/bindgen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uniffi-bindgen-cpp" -version = "0.9.0+v0.29.4" +version = "0.10.0+v0.31.2" edition = "2021" [dependencies] @@ -13,6 +13,6 @@ paste = "1" serde = "1" topological-sort = "0.2.2" textwrap = "0.16.0" -toml = "0.5" +toml = "0.9" uniffi_bindgen = { workspace = true } cargo_metadata = "0.19" diff --git a/bindgen/src/bindings/cpp/gen_cpp/compounds.rs b/bindgen/src/bindings/cpp/gen_cpp/compounds.rs index 1443802..ea1b571 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/compounds.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/compounds.rs @@ -1,5 +1,8 @@ use crate::bindings::cpp::CodeType; -use uniffi_bindgen::{backend::Type, interface::Literal, ComponentInterface}; +use uniffi_bindgen::{ + interface::{Literal, Type}, + ComponentInterface, +}; use crate::bindings::cpp::gen_cpp::filters::CppCodeOracle; diff --git a/bindgen/src/bindings/cpp/gen_cpp/enum_.rs b/bindgen/src/bindings/cpp/gen_cpp/enum_.rs index 6dd4ef9..0c81a9c 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/enum_.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/enum_.rs @@ -1,4 +1,4 @@ -use uniffi_bindgen::{backend::Literal, ComponentInterface}; +use uniffi_bindgen::{interface::Literal, ComponentInterface}; use crate::bindings::cpp::{ gen_cpp::filters::external_namespace_prefix, gen_cpp::filters::CppCodeOracle, CodeType, diff --git a/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs b/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs index b25fc02..e0f371f 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs @@ -1,7 +1,7 @@ use askama; use heck::{ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase}; use uniffi_bindgen::{ - interface::{Argument, AsType, FfiType, Literal, Object, Type, Variant}, + interface::{Argument, AsType, DefaultValue, FfiType, Literal, Object, Type, Variant}, ComponentInterface, }; @@ -273,11 +273,19 @@ pub(crate) fn object_names(obj: &Object) -> Result<(String, String)> { } pub(crate) fn literal_cpp( - literal: &Literal, + default: &DefaultValue, as_ct: &impl AsCodeType, enum_style: &EnumStyle, ci: &ComponentInterface, ) -> Result { + let literal = match default { + DefaultValue::Default => return Ok("{}".into()), + DefaultValue::Literal(Literal::Some { inner }) => { + return literal_cpp(inner, as_ct, enum_style, ci) + } + DefaultValue::Literal(literal) => literal, + }; + match literal { Literal::Enum(name, _) => Ok(format!( "{}::{}", @@ -339,7 +347,7 @@ pub(crate) fn ffi_type_name(ffi_type: &FfiType) -> Result { FfiType::Int64 => "int64_t".into(), FfiType::Float32 => "float".into(), FfiType::Float64 => "double".into(), - FfiType::RustArcPtr(_) | FfiType::VoidPointer => "void *".into(), + FfiType::VoidPointer => "void *".into(), FfiType::RustBuffer(_) => "RustBuffer".into(), FfiType::ForeignBytes => "ForeignBytes".into(), FfiType::Callback(_) => "void *".into(), diff --git a/bindgen/src/bindings/cpp/gen_cpp/miscellany.rs b/bindgen/src/bindings/cpp/gen_cpp/miscellany.rs index a8fa315..ef32ec7 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/miscellany.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/miscellany.rs @@ -1,6 +1,6 @@ use crate::bindings::cpp::CodeType; use paste::paste; -use uniffi_bindgen::{backend::Literal, ComponentInterface}; +use uniffi_bindgen::{interface::Literal, ComponentInterface}; macro_rules! impl_code_type_for_miscellany { ($T:ty, $label:literal, $canonical_name:literal) => { diff --git a/bindgen/src/bindings/cpp/gen_cpp/object.rs b/bindgen/src/bindings/cpp/gen_cpp/object.rs index 3088cba..4dd7fa2 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/object.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/object.rs @@ -1,4 +1,7 @@ -use uniffi_bindgen::{backend::Literal, interface::ObjectImpl, ComponentInterface}; +use uniffi_bindgen::{ + interface::{Literal, ObjectImpl}, + ComponentInterface, +}; use crate::bindings::cpp::{ gen_cpp::filters::callback_interface_name, gen_cpp::filters::external_namespace_prefix, diff --git a/bindgen/src/bindings/cpp/gen_cpp/primitives.rs b/bindgen/src/bindings/cpp/gen_cpp/primitives.rs index 19db704..11c5a50 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/primitives.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/primitives.rs @@ -1,6 +1,9 @@ use crate::bindings::cpp::CodeType; use paste::paste; -use uniffi_bindgen::{backend::Literal, interface::Radix, ComponentInterface}; +use uniffi_bindgen::{ + interface::{Literal, Radix}, + ComponentInterface, +}; fn render_literal(literal: &Literal) -> String { match literal { diff --git a/bindgen/src/bindings/cpp/gen_cpp/record.rs b/bindgen/src/bindings/cpp/gen_cpp/record.rs index e15ce0d..73d6605 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/record.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/record.rs @@ -1,4 +1,4 @@ -use uniffi_bindgen::{backend::Literal, ComponentInterface}; +use uniffi_bindgen::{interface::Literal, ComponentInterface}; use crate::bindings::cpp::{ gen_cpp::filters::external_namespace_prefix, gen_cpp::filters::CppCodeOracle, CodeType, diff --git a/bindgen/src/bindings/cpp/mod.rs b/bindgen/src/bindings/cpp/mod.rs index 7b938e7..7ccd27d 100644 --- a/bindgen/src/bindings/cpp/mod.rs +++ b/bindgen/src/bindings/cpp/mod.rs @@ -5,7 +5,7 @@ use std::{fmt::Debug, fs}; use anyhow::Result; use serde::{Deserialize, Serialize}; use uniffi_bindgen::{ - backend::Literal, BindingGenerator, Component, ComponentInterface, GenerationSettings, + interface::Literal, BindingGenerator, Component, ComponentInterface, GenerationSettings, }; use self::gen_cpp::{generate_cpp_bindings, Bindings}; @@ -93,9 +93,16 @@ impl BindingGenerator for CppBindingGenerator { components: &[uniffi_bindgen::Component], ) -> Result<()> { for Component { ci, config, .. } in components { - if ci.has_async_fns() || ci.has_async_callback_interface_definition() { + if ci.has_async_callback_interface_definition() { unimplemented!( - "Cpp bindgen does not support async functions! Namespace: {}", + "Cpp bindgen does not support async callback interfaces! Namespace: {}", + ci.namespace() + ); + } + + if ci.has_async_fns() { + eprintln!( + "Warning: omitting unsupported async functions from namespace: {}", ci.namespace() ); } diff --git a/bindgen/src/bindings/cpp/templates/callback.hpp b/bindgen/src/bindings/cpp/templates/callback.hpp index 54efb62..ea000f3 100644 --- a/bindgen/src/bindings/cpp/templates/callback.hpp +++ b/bindgen/src/bindings/cpp/templates/callback.hpp @@ -21,13 +21,15 @@ namespace uniffi { {%- endfor %} static void uniffi_free(uint64_t uniffi_handle); + static uint64_t uniffi_clone(uint64_t uniffi_handle); static void init(); private: static inline {{ vtable|ffi_type_name }} vtable = {{ vtable|ffi_type_name}} { + .uniffi_free = reinterpret_cast(&uniffi_free), + .uniffi_clone = reinterpret_cast(&uniffi_clone), {%- for (ffi_callback, meth) in vtable_methods.iter() %} .{{ meth.name()|var_name }} = reinterpret_cast(&{{ meth.name()|var_name }}), {%- endfor %} - .uniffi_free = reinterpret_cast(&uniffi_free) }; }; } diff --git a/bindgen/src/bindings/cpp/templates/callback_iface_tmpl.cpp b/bindgen/src/bindings/cpp/templates/callback_iface_tmpl.cpp index d881585..4ef44a3 100644 --- a/bindgen/src/bindings/cpp/templates/callback_iface_tmpl.cpp +++ b/bindgen/src/bindings/cpp/templates/callback_iface_tmpl.cpp @@ -42,6 +42,12 @@ void {{ trait_impl }}::uniffi_free(uint64_t uniffi_handle) { {{ ffi_converter_name }}::handle_map.erase(uniffi_handle); } +uint64_t {{ trait_impl }}::uniffi_clone(uint64_t uniffi_handle) { + return {{ ffi_converter_name }}::handle_map.insert( + {{ ffi_converter_name }}::handle_map.at(uniffi_handle) + ); +} + void {{ trait_impl }}::init() { {{ ffi_init_callback.name() }}(vtable); } diff --git a/bindgen/src/bindings/cpp/templates/enum.hpp b/bindgen/src/bindings/cpp/templates/enum.hpp index bcb687c..c52150f 100644 --- a/bindgen/src/bindings/cpp/templates/enum.hpp +++ b/bindgen/src/bindings/cpp/templates/enum.hpp @@ -24,7 +24,7 @@ struct {{ type_name }} { struct {{ variant|variant_name(config.enum_style) }} { {%- for field in variant.fields() %} {%- call macros::docstring(field, 8) %} - {{ field|type_name(ci) }} {{ field.name()|var_name }} + {{ field|type_name(ci) }} {% call macros::field_name(field, loop.index) %} {%- match field.default_value() %} {%- when Some with (literal) %} = {{ literal|literal_cpp(field, config.enum_style, ci) }};{%- else -%}; {%- endmatch %} diff --git a/bindgen/src/bindings/cpp/templates/enum_tmpl.cpp b/bindgen/src/bindings/cpp/templates/enum_tmpl.cpp index 48b947c..602890c 100644 --- a/bindgen/src/bindings/cpp/templates/enum_tmpl.cpp +++ b/bindgen/src/bindings/cpp/templates/enum_tmpl.cpp @@ -74,7 +74,7 @@ RustBuffer {{ ffi_converter_name }}::lower(const {{ type_name }} &val) { case {{ loop.index }}: return {{ type_name }}::{{ variant|variant_name(config.enum_style) }} { {%- for field in variant.fields() %} - .{{field.name()|var_name}} = {{ field|read_fn }}(stream), + .{% call macros::field_name(field, loop.index) %} = {{ field|read_fn }}(stream), {%- endfor %} }; {% endfor %} @@ -93,7 +93,7 @@ void {{ ffi_converter_name }}::write(RustStream &stream, const {{ type_name }} & {%- for variant in e.variants() %} {% if !loop.first %}else {% endif %}if constexpr (std::is_same_v) { {%- for field in variant.fields() %} - {{ field|write_fn }}(stream, {{ field.as_type()|cpp_deref(ci) }}arg.{{ field.name()|var_name }}); + {{ field|write_fn }}(stream, {{ field.as_type()|cpp_deref(ci) }}arg.{% call macros::field_name(field, loop.index) %}); {%- endfor %} } {%- endfor %} @@ -114,7 +114,7 @@ uint64_t {{ ffi_converter_name }}::allocation_size(const {{ type_name|class_name {% if !loop.first %}else {% endif %}if constexpr (std::is_same_v) { uint64_t size = 0; {%- for field in variant.fields() %} - size += {{ field|allocation_size_fn }}({{ field.as_type()|cpp_deref(ci) }}arg.{{ field.name()|var_name }}); + size += {{ field|allocation_size_fn }}({{ field.as_type()|cpp_deref(ci) }}arg.{% call macros::field_name(field, loop.index) %}); {%- endfor %} return size; } diff --git a/bindgen/src/bindings/cpp/templates/handle_map.cpp b/bindgen/src/bindings/cpp/templates/handle_map.cpp index 8607aa3..289e900 100644 --- a/bindgen/src/bindings/cpp/templates/handle_map.cpp +++ b/bindgen/src/bindings/cpp/templates/handle_map.cpp @@ -14,7 +14,8 @@ template struct HandleMap { auto handle = this->cur_handle; this->map.insert({ handle, impl }); - this->cur_handle += 1; + // UniFFI reserves odd values for handles created by foreign bindings. + this->cur_handle += 2; return handle; } @@ -39,6 +40,6 @@ template struct HandleMap { HandleMap &operator=(HandleMap &&) = delete; std::mutex mutex; - uint64_t cur_handle = 0; + uint64_t cur_handle = 1; std::map> map; }; diff --git a/bindgen/src/bindings/cpp/templates/obj.cpp b/bindgen/src/bindings/cpp/templates/obj.cpp index 3f1de51..a818598 100644 --- a/bindgen/src/bindings/cpp/templates/obj.cpp +++ b/bindgen/src/bindings/cpp/templates/obj.cpp @@ -14,9 +14,9 @@ namespace uniffi { {%- endif %} -{{ impl_class_name }}::{{ impl_class_name }}(void *ptr): instance(ptr) {} +{{ impl_class_name }}::{{ impl_class_name }}(uint64_t handle): instance(handle) {} -{{ impl_class_name }}::{{ impl_class_name }}(const {{ impl_class_name }} &other) : instance(nullptr) { +{{ impl_class_name }}::{{ impl_class_name }}(const {{ impl_class_name }} &other) : instance(0) { if (other.instance) { instance = other._uniffi_internal_clone_pointer(); } @@ -30,21 +30,26 @@ namespace uniffi { {% match obj.primary_constructor() -%} {%- when Some with (ctor) %} +{%- if !ctor.is_async() %} {{ type_name }} {{ impl_class_name }}::init({% call macros::param_list(ctor) %}) { return {{ type_name }}( new {{ impl_class_name }}({%- call macros::rust_call(ctor) -%}) ); } +{%- endif %} {% else -%} {% endmatch -%} {% for ctor in obj.alternate_constructors() %} +{%- if !ctor.is_async() %} {{ type_name }} {{ impl_class_name }}::{{ ctor.name() }}({% call macros::param_list(ctor) %}) { return {{ type_name }}(new {{ impl_class_name }}({% call macros::rust_call(ctor) %})); } +{%- endif %} {% endfor %} {%- for method in obj.methods() %} +{%- if !method.is_async() %} {% match method.return_type() %}{% when Some with (return_type) %}{{ return_type|type_name(ci) }} {% else %}void {% endmatch -%} {{ impl_class_name }}::{{ method.name()|fn_name }}({% call macros::param_list(method) %}) { auto ptr = this->_uniffi_internal_clone_pointer(); @@ -55,6 +60,7 @@ namespace uniffi { {% call macros::rust_call_with_prefix("ptr", method) -%}; {%- endmatch %} } +{%- endif %} {%- endfor %} {{ impl_class_name }}::~{{ impl_class_name }}() { @@ -65,7 +71,7 @@ namespace uniffi { ); } -void *{{ impl_class_name }}::_uniffi_internal_clone_pointer() const { +uint64_t {{ impl_class_name }}::_uniffi_internal_clone_pointer() const { return uniffi::rust_call( {{ obj.ffi_object_clone().name() }}, nullptr, @@ -94,5 +100,9 @@ bool {{ impl_class_name }}::ne(const {{ type_name }} &other) const { uint64_t {{ impl_class_name }}::hash() const { return uniffi::{{ Type::UInt64.borrow()|lift_fn }}({% call macros::rust_call_with_prefix("this->_uniffi_internal_clone_pointer()", hash) %}); } +{% when UniffiTrait::Ord { cmp } %} +int8_t {{ impl_class_name }}::cmp(const {{ type_name }} &other) const { + return uniffi::{{ Type::Int8.borrow()|lift_fn }}({% call macros::rust_call_with_prefix("this->_uniffi_internal_clone_pointer()", cmp) %}); +} {% endmatch %} {%- endfor %} diff --git a/bindgen/src/bindings/cpp/templates/obj.hpp b/bindgen/src/bindings/cpp/templates/obj.hpp index fb02106..c0398ac 100644 --- a/bindgen/src/bindings/cpp/templates/obj.hpp +++ b/bindgen/src/bindings/cpp/templates/obj.hpp @@ -38,20 +38,26 @@ struct {{ impl_class_name }} {%- match obj.primary_constructor() %} {%- when Some with (ctor) %} + {%- if !ctor.is_async() %} {%- call macros::docstring(ctor, 4) %} static {{ type_name }} init({% call macros::param_list(ctor) %}); + {%- endif %} {%- else %} {%- endmatch %} {%- for ctor in obj.alternate_constructors() %} + {%- if !ctor.is_async() %} {%- call macros::docstring(ctor, 4) %} static {{ type_name }} {{ ctor.name() }}({% call macros::param_list(ctor) %}); + {%- endif %} {%- endfor %} {%- for method in obj.methods() %} + {%- if !method.is_async() %} {%- call macros::docstring(method, 4) %} {% match method.return_type() %}{% when Some with (return_type) %}{{ return_type|type_name(ci) }} {% else %}void {% endmatch %} {{- method.name()|fn_name }}({% call macros::param_list(method) %}); + {%- endif %} {%- endfor %} {%- for method in obj.uniffi_traits() %} @@ -80,6 +86,11 @@ struct {{ impl_class_name }} * Returns a hash of the object, internally calls Rust's `Hash` trait. */ uint64_t hash() const; + {%- when UniffiTrait::Ord { cmp } %} + /** + * Three-way comparison, internally calls Rust's `Ord` trait. + */ + int8_t cmp(const {{ type_name }} &other) const; {%- endmatch %} {%- endfor %} @@ -89,9 +100,9 @@ struct {{ impl_class_name }} private: {{ impl_class_name }}(const {{ impl_class_name }} &); - {{ impl_class_name }}(void *); + {{ impl_class_name }}(uint64_t); - void *_uniffi_internal_clone_pointer() const; + uint64_t _uniffi_internal_clone_pointer() const; - void *instance = nullptr; + uint64_t instance = 0; }; diff --git a/bindgen/src/bindings/cpp/templates/obj_conv.cpp b/bindgen/src/bindings/cpp/templates/obj_conv.cpp index 27f70ef..2bb7bbe 100644 --- a/bindgen/src/bindings/cpp/templates/obj_conv.cpp +++ b/bindgen/src/bindings/cpp/templates/obj_conv.cpp @@ -12,28 +12,37 @@ } {% endif %} -{{ type_name }} {{ ffi_converter_name }}::lift(void *ptr) { - return {{ type_name }}(new {{ impl_class_name }}(ptr)); +{{ type_name }} {{ ffi_converter_name }}::lift(uint64_t handle) { + {%- if obj.has_callback_interface() %} + if ((handle & 1) == 1) { + auto obj = handle_map.at(handle); + handle_map.erase(handle); + return obj; + } + {%- endif %} + return {{ type_name }}(new {{ impl_class_name }}(handle)); } -void *{{ ffi_converter_name }}::lower(const {{ type_name }} &obj) { +uint64_t {{ ffi_converter_name }}::lower(const {{ type_name }} &obj) { {%- if obj.has_callback_interface() %} - auto ptr = handle_map.insert(obj); - return reinterpret_cast(ptr); + if (auto rust_obj = std::dynamic_pointer_cast<{{ impl_class_name }}>(obj)) { + return rust_obj->_uniffi_internal_clone_pointer(); + } + return handle_map.insert(obj); {%- else %} return reinterpret_cast<{{ impl_class_name}}*>(obj.get())->_uniffi_internal_clone_pointer(); {%- endif %} } {{ type_name }} {{ ffi_converter_name }}::read(RustStream &stream) { - std::uintptr_t ptr; - stream >> ptr; + uint64_t handle; + stream >> handle; - return {{ ffi_converter_name}}::lift(reinterpret_cast(ptr)); + return {{ ffi_converter_name}}::lift(handle); } void {{ ffi_converter_name }}::write(RustStream &stream, const {{ type_name }} &obj) { - stream << reinterpret_cast({{ ffi_converter_name }}::lower(obj)); + stream << {{ ffi_converter_name }}::lower(obj); } uint64_t {{ ffi_converter_name }}::allocation_size(const {{ type_name }} &) { diff --git a/bindgen/src/bindings/cpp/templates/obj_conv.hpp b/bindgen/src/bindings/cpp/templates/obj_conv.hpp index 682f408..e19f802 100644 --- a/bindgen/src/bindings/cpp/templates/obj_conv.hpp +++ b/bindgen/src/bindings/cpp/templates/obj_conv.hpp @@ -10,8 +10,8 @@ struct {{ typ|ffi_error_converter_name}} { {% endif %} struct {{ typ|ffi_converter_name }} { - static {{ type_name }} lift(void *); - static void *lower(const {{ type_name }} &); + static {{ type_name }} lift(uint64_t); + static uint64_t lower(const {{ type_name }} &); static {{ type_name }} read(RustStream &); static void write(RustStream &, const {{ type_name }} &); static uint64_t allocation_size(const {{ type_name }} &); diff --git a/bindgen/src/bindings/cpp/templates/scaffolding/macros.cpp b/bindgen/src/bindings/cpp/templates/scaffolding/macros.cpp index d8ff781..5292f5f 100644 --- a/bindgen/src/bindings/cpp/templates/scaffolding/macros.cpp +++ b/bindgen/src/bindings/cpp/templates/scaffolding/macros.cpp @@ -73,3 +73,11 @@ obj->{{ scaffolding_fn.name() }}( {% endfor %} {%- if ffi_func.has_rust_call_status_arg() %}RustCallStatus *out_status{% endif -%}) {% endmacro %} + +{% macro field_name(field, field_num) %} +{%- if field.name().is_empty() -%} +v{{- field_num -}} +{%- else -%} +{{ field.name()|var_name }} +{%- endif -%} +{%- endmacro %} diff --git a/bindgen/src/bindings/cpp/templates/scaffolding/obj.cpp b/bindgen/src/bindings/cpp/templates/scaffolding/obj.cpp index 240d41b..e36458d 100644 --- a/bindgen/src/bindings/cpp/templates/scaffolding/obj.cpp +++ b/bindgen/src/bindings/cpp/templates/scaffolding/obj.cpp @@ -1,17 +1,16 @@ -{{ type_name }} {{ ffi_converter_name }}::lift(void *ptr) { - return {{ name }}_map.at((uint64_t)ptr); +{{ type_name }} {{ ffi_converter_name }}::lift(uint64_t handle) { + return {{ name }}_map.at(handle); } -void *{{ ffi_converter_name }}::lower(const {{ type_name }} &obj) { - auto ret = {{ name }}_map.insert(obj); - return (void *)ret; +uint64_t {{ ffi_converter_name }}::lower(const {{ type_name }} &obj) { + return {{ name }}_map.insert(obj); } {{ type_name }} {{ ffi_converter_name }}::read(RustStream &stream) { - std::uintptr_t ptr; - stream >> ptr; + uint64_t handle; + stream >> handle; - return {{ name }}_map.at(ptr); + return {{ name }}_map.at(handle); } void {{ ffi_converter_name }}::write(RustStream &stream, const {{ type_name }} &obj) { diff --git a/bindgen/src/bindings/cpp/templates/scaffolding/obj.hpp b/bindgen/src/bindings/cpp/templates/scaffolding/obj.hpp index 5d69641..c2acefe 100644 --- a/bindgen/src/bindings/cpp/templates/scaffolding/obj.hpp +++ b/bindgen/src/bindings/cpp/templates/scaffolding/obj.hpp @@ -1,7 +1,7 @@ {%- let type_name = typ|type_name(ci) %} struct {{ typ|ffi_converter_name }} { - static {{ type_name }} lift(void *); - static void *lower(const {{ type_name }} &); + static {{ type_name }} lift(uint64_t); + static uint64_t lower(const {{ type_name }} &); static {{ type_name }} read(RustStream &); static void write(RustStream &, const {{ type_name }} &); static int32_t allocation_size(const {{ type_name }} &); diff --git a/bindgen/src/bindings/cpp/templates/wrapper.cpp b/bindgen/src/bindings/cpp/templates/wrapper.cpp index b3ebc23..2473e82 100644 --- a/bindgen/src/bindings/cpp/templates/wrapper.cpp +++ b/bindgen/src/bindings/cpp/templates/wrapper.cpp @@ -127,6 +127,8 @@ void rust_call_trait_interface_with_error(RustCallStatus* status, F make_call, W {{ type_helper_code }} {%- for func in ci.function_definitions() %} +{%- if !func.is_async() %} {% include "fn_def.cpp" %} +{%- endif %} {% endfor -%} } // namespace {{ namespace }} diff --git a/bindgen/src/bindings/cpp/templates/wrapper.hpp b/bindgen/src/bindings/cpp/templates/wrapper.hpp index 462b5f2..91f1738 100644 --- a/bindgen/src/bindings/cpp/templates/wrapper.hpp +++ b/bindgen/src/bindings/cpp/templates/wrapper.hpp @@ -170,6 +170,7 @@ void rustbuffer_free(RustBuffer); } // namespace uniffi {%~ for func in ci.function_definitions() %} +{%- if !func.is_async() %} {%- call macros::docstring(func, 0) %} {%- match func.return_type() %} {%- when Some with (return_type) %} @@ -177,5 +178,6 @@ void rustbuffer_free(RustBuffer); {%- when None %} void {{ func.name()|fn_name }}({% call macros::param_list(func) %}); {%- endmatch %} +{%- endif %} {%- endfor %} } // namespace {{ namespace }} diff --git a/cpp-tests/tests/coverall/main.cpp b/cpp-tests/tests/coverall/main.cpp index 385a8e6..b2a05a2 100644 --- a/cpp-tests/tests/coverall/main.cpp +++ b/cpp-tests/tests/coverall/main.cpp @@ -447,7 +447,7 @@ void test_path() { ASSERT_EQ(2, traits[1]->strong_count()); traits[0]->set_parent(traits[1]); - ASSERT_EQ(2, traits[1]->strong_count()); + ASSERT_EQ(3, traits[1]->strong_count()); ASSERT_EQ(std::vector {"node-2"} , coverall::ancestor_names(traits[0])); ASSERT_EQ(std::vector {} , coverall::ancestor_names(traits[1])); diff --git a/fixtures/Cargo.toml b/fixtures/Cargo.toml index 476486c..197551d 100644 --- a/fixtures/Cargo.toml +++ b/fixtures/Cargo.toml @@ -7,19 +7,19 @@ edition = "2021" crate-type = ["cdylib", "lib", "staticlib"] [dependencies] -uniffi-example-arithmetic = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-example-callbacks = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-example-custom-types = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-example-geometry = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-example-rondpoint = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-example-sprites = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-example-todolist = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-example-traits = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-fixture-callbacks = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-fixture-coverall = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-fixture-docstring = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-fixture-time = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } -uniffi-fixture-trait-methods = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.29.4" } +uniffi-example-arithmetic = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-example-callbacks = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-example-custom-types = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-example-geometry = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-example-rondpoint = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-example-sprites = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-example-todolist = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-example-traits = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-fixture-callbacks = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-fixture-coverall = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-fixture-docstring = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-fixture-time = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } +uniffi-fixture-trait-methods = { git = "https://github.com/mozilla/uniffi-rs.git", tag = "v0.31.2" } uniffi-error-types-builtin = { path = "error-types-builtin" } uniffi-custom-types-builtin = { path = "custom-types-builtin" } diff --git a/fixtures/ext-types-export/src/lib.rs b/fixtures/ext-types-export/src/lib.rs index 593d6cf..b411b96 100644 --- a/fixtures/ext-types-export/src/lib.rs +++ b/fixtures/ext-types-export/src/lib.rs @@ -32,6 +32,7 @@ impl Counter { self.value.load(std::sync::atomic::Ordering::SeqCst) } } +#[uniffi::trait_interface] pub trait Greeter: Send + Sync { fn greet(&self) -> String; } @@ -41,6 +42,7 @@ pub enum Shape { Rectangle { width: f64, height: f64 }, } +#[uniffi::trait_interface] pub trait Vehicle: Send + Sync { fn year(&self) -> i32; } From cf5ac7ccf76c7e6e1994510bbc86f0df64c96e49 Mon Sep 17 00:00:00 2001 From: Alan George Date: Tue, 1 Sep 2026 14:39:34 -0600 Subject: [PATCH 2/6] Duplicate enum guarding --- bindgen/src/bindings/cpp/gen_cpp/mod.rs | 13 +++++++++++-- cpp-tests/tests/enum_style_test/main.cpp | 7 +++++++ fixtures/enum-style-test/src/enum_style_test.udl | 9 +++++++++ fixtures/enum-style-test/src/lib.rs | 9 +++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/bindgen/src/bindings/cpp/gen_cpp/mod.rs b/bindgen/src/bindings/cpp/gen_cpp/mod.rs index e6b0ae0..2822985 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/mod.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/mod.rs @@ -193,9 +193,18 @@ impl<'a> CppWrapperHeader<'a> { .collect::>(); let mut sorted: Vec = Vec::new(); + let mut emitted_names = BTreeSet::new(); while !definition_topology.peek_all().is_empty() { - let list = definition_topology.pop_all(); + let mut list = definition_topology.pop_all(); + list.sort(); for name in list { + // TopologicalSort preserves duplicate dependency links. A record or + // rich enum can mention the same named type more than once, causing + // that type to be returned once per link. Definitions, however, + // must be emitted exactly once. + if !emitted_names.insert(name) { + continue; + } match self.ci.get_type(name) { // External types are defined in their own namespace's header with their own // converters declared, which we `#include`. They must not enter the local @@ -214,7 +223,7 @@ impl<'a> CppWrapperHeader<'a> { } let rest = types - .filter(|&t| !sorted.contains(t)) + .filter(|t| type_name(t).map_or(true, |name| !emitted_names.contains(name))) .cloned() .collect::>(); diff --git a/cpp-tests/tests/enum_style_test/main.cpp b/cpp-tests/tests/enum_style_test/main.cpp index 6c82a36..1848ba2 100644 --- a/cpp-tests/tests/enum_style_test/main.cpp +++ b/cpp-tests/tests/enum_style_test/main.cpp @@ -9,5 +9,12 @@ int main() { auto complex = enum_style_test::get_complex_enum(); enum_style_test::set_complex_enum(complex); + auto repeated = enum_style_test::roundtrip_repeated_dependencies({ + enum_style_test::SimpleEnum::VARIANT_ONE, + enum_style_test::SimpleEnum::VARIANT_TWO, + }); + ASSERT_EQ(repeated.first, enum_style_test::SimpleEnum::VARIANT_ONE); + ASSERT_EQ(repeated.second, enum_style_test::SimpleEnum::VARIANT_TWO); + return 0; } diff --git a/fixtures/enum-style-test/src/enum_style_test.udl b/fixtures/enum-style-test/src/enum_style_test.udl index b805102..d12e633 100644 --- a/fixtures/enum-style-test/src/enum_style_test.udl +++ b/fixtures/enum-style-test/src/enum_style_test.udl @@ -10,10 +10,19 @@ interface ComplexEnum { VariantTwo(f32 flt); }; +// Repeating the same named dependency used to make the C++ topological sorter +// emit that dependency's definition more than once. +dictionary RepeatedDependencies { + SimpleEnum first; + SimpleEnum second; +}; + namespace enum_style_test { SimpleEnum get_simple_enum(); void set_simple_enum(SimpleEnum e); ComplexEnum get_complex_enum(); void set_complex_enum(ComplexEnum e); + + RepeatedDependencies roundtrip_repeated_dependencies(RepeatedDependencies value); }; diff --git a/fixtures/enum-style-test/src/lib.rs b/fixtures/enum-style-test/src/lib.rs index 067a6e7..38644bf 100644 --- a/fixtures/enum-style-test/src/lib.rs +++ b/fixtures/enum-style-test/src/lib.rs @@ -9,6 +9,11 @@ enum ComplexEnum { VariantTwo { flt: f32 }, } +struct RepeatedDependencies { + first: SimpleEnum, + second: SimpleEnum, +} + fn get_simple_enum() -> SimpleEnum { SimpleEnum::VariantOne } @@ -21,4 +26,8 @@ fn get_complex_enum() -> ComplexEnum { fn set_complex_enum(_: ComplexEnum) {} +fn roundtrip_repeated_dependencies(value: RepeatedDependencies) -> RepeatedDependencies { + value +} + uniffi::include_scaffolding!("enum_style_test"); From 11b5d815fdc6ae8edb38f05ba1d4704da66c1eb3 Mon Sep 17 00:00:00 2001 From: Alan George Date: Tue, 15 Sep 2026 09:23:52 -0600 Subject: [PATCH 3/6] Fix optional enum default rendering --- bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs | 4 ++-- cpp-tests/tests/enum_style_test/main.cpp | 5 +++++ fixtures/enum-style-test/src/enum_style_test.udl | 5 +++++ fixtures/enum-style-test/src/lib.rs | 8 ++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs b/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs index e0f371f..d958a89 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs @@ -287,9 +287,9 @@ pub(crate) fn literal_cpp( }; match literal { - Literal::Enum(name, _) => Ok(format!( + Literal::Enum(name, type_) => Ok(format!( "{}::{}", - as_ct.as_codetype().type_label(ci), + CppCodeOracle.find(type_).type_label(ci), CppCodeOracle.enum_variant_name(&name, enum_style), )), _ => Ok(as_ct.as_codetype().literal(literal, ci)), diff --git a/cpp-tests/tests/enum_style_test/main.cpp b/cpp-tests/tests/enum_style_test/main.cpp index 1848ba2..92d0498 100644 --- a/cpp-tests/tests/enum_style_test/main.cpp +++ b/cpp-tests/tests/enum_style_test/main.cpp @@ -16,5 +16,10 @@ int main() { ASSERT_EQ(repeated.first, enum_style_test::SimpleEnum::VARIANT_ONE); ASSERT_EQ(repeated.second, enum_style_test::SimpleEnum::VARIANT_TWO); + enum_style_test::OptionalEnumDefault optional_enum_default; + ASSERT_EQ(optional_enum_default.value, enum_style_test::SimpleEnum::VARIANT_ONE); + auto roundtripped = enum_style_test::roundtrip_optional_enum_default(optional_enum_default); + ASSERT_EQ(roundtripped.value, enum_style_test::SimpleEnum::VARIANT_ONE); + return 0; } diff --git a/fixtures/enum-style-test/src/enum_style_test.udl b/fixtures/enum-style-test/src/enum_style_test.udl index d12e633..5366b26 100644 --- a/fixtures/enum-style-test/src/enum_style_test.udl +++ b/fixtures/enum-style-test/src/enum_style_test.udl @@ -17,6 +17,10 @@ dictionary RepeatedDependencies { SimpleEnum second; }; +dictionary OptionalEnumDefault { + SimpleEnum? value = "VariantOne"; +}; + namespace enum_style_test { SimpleEnum get_simple_enum(); void set_simple_enum(SimpleEnum e); @@ -25,4 +29,5 @@ namespace enum_style_test { void set_complex_enum(ComplexEnum e); RepeatedDependencies roundtrip_repeated_dependencies(RepeatedDependencies value); + OptionalEnumDefault roundtrip_optional_enum_default(OptionalEnumDefault value); }; diff --git a/fixtures/enum-style-test/src/lib.rs b/fixtures/enum-style-test/src/lib.rs index 38644bf..44d3c30 100644 --- a/fixtures/enum-style-test/src/lib.rs +++ b/fixtures/enum-style-test/src/lib.rs @@ -14,6 +14,10 @@ struct RepeatedDependencies { second: SimpleEnum, } +struct OptionalEnumDefault { + value: Option, +} + fn get_simple_enum() -> SimpleEnum { SimpleEnum::VariantOne } @@ -30,4 +34,8 @@ fn roundtrip_repeated_dependencies(value: RepeatedDependencies) -> RepeatedDepen value } +fn roundtrip_optional_enum_default(value: OptionalEnumDefault) -> OptionalEnumDefault { + value +} + uniffi::include_scaffolding!("enum_style_test"); From 640ecfa54bb32e804d9ff97e72926ca8d07f1dc0 Mon Sep 17 00:00:00 2001 From: Alan George Date: Wed, 16 Sep 2026 09:22:49 -0600 Subject: [PATCH 4/6] Clarify default value naming --- bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs b/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs index d958a89..1aa195a 100644 --- a/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs +++ b/bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs @@ -273,12 +273,12 @@ pub(crate) fn object_names(obj: &Object) -> Result<(String, String)> { } pub(crate) fn literal_cpp( - default: &DefaultValue, + default_value: &DefaultValue, as_ct: &impl AsCodeType, enum_style: &EnumStyle, ci: &ComponentInterface, ) -> Result { - let literal = match default { + let literal = match default_value { DefaultValue::Default => return Ok("{}".into()), DefaultValue::Literal(Literal::Some { inner }) => { return literal_cpp(inner, as_ct, enum_style, ci) From 433eae1cadba3acae81012aa247fe4a94ab91d60 Mon Sep 17 00:00:00 2001 From: Alan George Date: Mon, 14 Sep 2026 18:06:37 -0600 Subject: [PATCH 5/6] Generate C++17-compatible bindings --- README.md | 2 +- .../src/bindings/cpp/templates/callback.hpp | 12 ++-- .../cpp/templates/cpp_scaffolding.cpp | 28 ++++----- .../src/bindings/cpp/templates/enum_tmpl.cpp | 2 +- .../cpp/templates/rust_buf_stream.cpp | 11 +++- .../cpp/templates/scaffolding/callback.cpp | 20 +++---- .../cpp/templates/scaffolding/object_map.cpp | 5 +- .../src/bindings/cpp/templates/wrapper.hpp | 1 - cpp-tests/CMakeLists.txt | 8 ++- cpp-tests/tests/coverall/main.cpp | 7 ++- cpp-tests/tests/rondpoint/main.cpp | 58 +++++++++---------- docs/SCAFFOLDING.md | 4 +- 12 files changed, 83 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index bc06eef..5409f69 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Regardless of the generation method, these files are produced: # How to integrate bindings To integrate the bindings into your projects, simply add the generated bindings files to your project. -C++20 is required to compile the bindings. +C++17 or newer is required to compile the bindings. # Unsupported features diff --git a/bindgen/src/bindings/cpp/templates/callback.hpp b/bindgen/src/bindings/cpp/templates/callback.hpp index ea000f3..2ecfbc1 100644 --- a/bindgen/src/bindings/cpp/templates/callback.hpp +++ b/bindgen/src/bindings/cpp/templates/callback.hpp @@ -24,12 +24,14 @@ namespace uniffi { static uint64_t uniffi_clone(uint64_t uniffi_handle); static void init(); private: - static inline {{ vtable|ffi_type_name }} vtable = {{ vtable|ffi_type_name}} { - .uniffi_free = reinterpret_cast(&uniffi_free), - .uniffi_clone = reinterpret_cast(&uniffi_clone), + static inline {{ vtable|ffi_type_name }} vtable = [] { + {{ vtable|ffi_type_name }} value{}; + value.uniffi_free = reinterpret_cast(&uniffi_free); + value.uniffi_clone = reinterpret_cast(&uniffi_clone); {%- for (ffi_callback, meth) in vtable_methods.iter() %} - .{{ meth.name()|var_name }} = reinterpret_cast(&{{ meth.name()|var_name }}), + value.{{ meth.name()|var_name }} = reinterpret_cast(&{{ meth.name()|var_name }}); {%- endfor %} - }; + return value; + }(); }; } diff --git a/bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp b/bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp index 55bd69a..d8591e4 100644 --- a/bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp +++ b/bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -125,11 +124,10 @@ extern "C" { UNIFFI_EXPORT RustBuffer {{ ci.ffi_rustbuffer_alloc().name() }}(int32_t size, RustCallStatus *out_status) { out_status->code = UNIFFI_CALL_STATUS_OK; - RustBuffer buf = { - .capacity = size, - .len = size, - .data = new uint8_t[size], - }; + RustBuffer buf{}; + buf.capacity = size; + buf.len = size; + buf.data = new uint8_t[size]; return std::move(buf); } @@ -137,11 +135,10 @@ UNIFFI_EXPORT RustBuffer {{ ci.ffi_rustbuffer_alloc().name() }}(int32_t size, Ru UNIFFI_EXPORT RustBuffer {{ ci.ffi_rustbuffer_from_bytes().name() }}(ForeignBytes bytes, RustCallStatus *out_status) { out_status->code = UNIFFI_CALL_STATUS_OK; - RustBuffer buf = { - .capacity = bytes.len, - .len = bytes.len, - .data = new uint8_t[bytes.len], - }; + RustBuffer buf{}; + buf.capacity = bytes.len; + buf.len = bytes.len; + buf.data = new uint8_t[bytes.len]; std::copy(bytes.data, bytes.data + bytes.len, buf.data); @@ -157,11 +154,10 @@ UNIFFI_EXPORT void {{ ci.ffi_rustbuffer_free().name() }}(RustBuffer buf, RustCal UNIFFI_EXPORT RustBuffer {{ ci.ffi_rustbuffer_reserve().name() }}(RustBuffer buffer, int32_t additional, RustCallStatus *out_status) { out_status->code = UNIFFI_CALL_STATUS_OK; - RustBuffer buf = { - .capacity = buffer.capacity + additional, - .len = buffer.len, - .data = (uint8_t*)std::realloc(buffer.data, buffer.capacity + additional), - }; + RustBuffer buf{}; + buf.capacity = buffer.capacity + additional; + buf.len = buffer.len; + buf.data = (uint8_t*)std::realloc(buffer.data, buffer.capacity + additional); return std::move(buf); } diff --git a/bindgen/src/bindings/cpp/templates/enum_tmpl.cpp b/bindgen/src/bindings/cpp/templates/enum_tmpl.cpp index 602890c..faddc61 100644 --- a/bindgen/src/bindings/cpp/templates/enum_tmpl.cpp +++ b/bindgen/src/bindings/cpp/templates/enum_tmpl.cpp @@ -74,7 +74,7 @@ RustBuffer {{ ffi_converter_name }}::lower(const {{ type_name }} &val) { case {{ loop.index }}: return {{ type_name }}::{{ variant|variant_name(config.enum_style) }} { {%- for field in variant.fields() %} - .{% call macros::field_name(field, loop.index) %} = {{ field|read_fn }}(stream), + {{ field|read_fn }}(stream), {%- endfor %} }; {% endfor %} diff --git a/bindgen/src/bindings/cpp/templates/rust_buf_stream.cpp b/bindgen/src/bindings/cpp/templates/rust_buf_stream.cpp index 194c5d7..c2c248a 100644 --- a/bindgen/src/bindings/cpp/templates/rust_buf_stream.cpp +++ b/bindgen/src/bindings/cpp/templates/rust_buf_stream.cpp @@ -23,7 +23,7 @@ struct RustStream: std::basic_iostream { RustStream &operator>>(T &val) { read(reinterpret_cast(&val), sizeof(T)); - if (std::endian::native != std::endian::big) { + if (native_byte_order_is_little_endian()) { auto bytes = reinterpret_cast(&val); std::reverse(bytes, bytes + sizeof(T)); @@ -34,7 +34,7 @@ struct RustStream: std::basic_iostream { template >> RustStream &operator<<(T val) { - if (std::endian::native != std::endian::big) { + if (native_byte_order_is_little_endian()) { auto bytes = reinterpret_cast(&val); std::reverse(bytes, bytes + sizeof(T)); @@ -45,6 +45,11 @@ struct RustStream: std::basic_iostream { return *this; } private: + // Avoid platform-specific endian APIs while retaining C++17 compatibility. + static bool native_byte_order_is_little_endian() { + const uint16_t value = 1; + return *reinterpret_cast(&value) == 1; + } + RustStreamBuffer streambuf; }; - diff --git a/bindgen/src/bindings/cpp/templates/scaffolding/callback.cpp b/bindgen/src/bindings/cpp/templates/scaffolding/callback.cpp index 8543ffd..db4582b 100644 --- a/bindgen/src/bindings/cpp/templates/scaffolding/callback.cpp +++ b/bindgen/src/bindings/cpp/templates/scaffolding/callback.cpp @@ -11,11 +11,10 @@ class {{ iface.name() }}Proxy: public {{ iface.name() }} { ~{{ iface.name() }}Proxy() override { ForeignCallback *callback_stub = reinterpret_cast({{ ffi_converter_name|class_name }}::fn_handle.load()); - RustBuffer out_buf = { - .capacity = 0, - .len = 0, - .data = nullptr, - }; + RustBuffer out_buf{}; + out_buf.capacity = 0; + out_buf.len = 0; + out_buf.data = nullptr; callback_stub(this->handle, 0, nullptr, 0, &out_buf); @@ -33,11 +32,10 @@ class {{ iface.name() }}Proxy: public {{ iface.name() }} { throw std::runtime_error("callback stub not initialized, this indicates a bug in the generated code"); } - RustBuffer out_buf = { - .capacity = 0, - .len = 0, - .data = nullptr, - }; + RustBuffer out_buf{}; + out_buf.capacity = 0; + out_buf.len = 0; + out_buf.data = nullptr; int32_t size = 0; {% for arg in m.arguments() %} @@ -131,5 +129,3 @@ int32_t {{ ffi_converter_name|class_name }}::allocation_size(const {{ type_name } std::atomic {{ ffi_converter_name|class_name }}::fn_handle = 0; - - diff --git a/bindgen/src/bindings/cpp/templates/scaffolding/object_map.cpp b/bindgen/src/bindings/cpp/templates/scaffolding/object_map.cpp index a48ca78..f08205f 100644 --- a/bindgen/src/bindings/cpp/templates/scaffolding/object_map.cpp +++ b/bindgen/src/bindings/cpp/templates/scaffolding/object_map.cpp @@ -11,8 +11,9 @@ template struct ObjectMap { std::lock_guard guard(this->mutex); auto key = (uint64_t)impl.get(); - if (this->map.contains(key)) { - this->map.at(key).ref_count += 1; + auto it = this->map.find(key); + if (it != this->map.end()) { + it->second.ref_count += 1; } else { this->map.insert({ key, {impl, 1} }); } diff --git a/bindgen/src/bindings/cpp/templates/wrapper.hpp b/bindgen/src/bindings/cpp/templates/wrapper.hpp index 91f1738..97842e7 100644 --- a/bindgen/src/bindings/cpp/templates/wrapper.hpp +++ b/bindgen/src/bindings/cpp/templates/wrapper.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include #include diff --git a/cpp-tests/CMakeLists.txt b/cpp-tests/CMakeLists.txt index 0d946cd..1243070 100644 --- a/cpp-tests/CMakeLists.txt +++ b/cpp-tests/CMakeLists.txt @@ -1,9 +1,15 @@ cmake_minimum_required(VERSION 3.10) project(binding-tests VERSION 1.0.0 LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +if (MSVC) + add_compile_options(/permissive-) +else() + add_compile_options(-pedantic-errors) +endif() + include(CTest) enable_testing() diff --git a/cpp-tests/tests/coverall/main.cpp b/cpp-tests/tests/coverall/main.cpp index b2a05a2..2393cd5 100644 --- a/cpp-tests/tests/coverall/main.cpp +++ b/cpp-tests/tests/coverall/main.cpp @@ -261,7 +261,10 @@ void test_interface_in_dicts() { auto coveralls = coverall::Coveralls::init("test_interface_in_dicts"); coveralls->add_patch(coverall::Patch::init(coverall::Color::kRed)); - coveralls->add_repair(coverall::Repair {.when = std::chrono::system_clock::now(), .patch = coverall::Patch::init(coverall::Color::kGreen)}); + coverall::Repair repair; + repair.when = std::chrono::system_clock::now(); + repair.patch = coverall::Patch::init(coverall::Color::kGreen); + coveralls->add_repair(repair); ASSERT_EQ(2, coveralls->get_repairs().size()); } @@ -315,7 +318,7 @@ void test_dict_with_non_string_keys() { void test_return_only_dict() { auto d = coverall::ReturnOnlyDict{ - .e = std::make_shared() + std::make_shared() }; EXPECT_EXCEPTION(coverall::try_input_return_only_dict(d), std::runtime_error); } diff --git a/cpp-tests/tests/rondpoint/main.cpp b/cpp-tests/tests/rondpoint/main.cpp index 5b8ae87..2fa9e13 100644 --- a/cpp-tests/tests/rondpoint/main.cpp +++ b/cpp-tests/tests/rondpoint/main.cpp @@ -26,10 +26,10 @@ void affirm_enchaine(const T& c, const F& func, Args&& ...arg) { void test_copy() { auto dict = rondpoint::Dictionnaire { - .un = rondpoint::Enumeration::kDeux, - .deux = true, - .petit_nombre = 0, - .gros_nombre = 123456789u + rondpoint::Enumeration::kDeux, + true, + 0, + 123456789u }; auto copied_dict = rondpoint::copie_dictionnaire(dict); ASSERT_EQ(dict.un, copied_dict.un); @@ -44,8 +44,8 @@ void test_copy() { auto map = std::unordered_map { { "zero", rondpoint::EnumerationAvecDonnees::kZero {}}, - { "un", rondpoint::EnumerationAvecDonnees::kUn {.premier = 2}}, - { "deux", rondpoint::EnumerationAvecDonnees::kDeux {.premier= 1, .second = "test"}} + { "un", rondpoint::EnumerationAvecDonnees::kUn {2}}, + { "deux", rondpoint::EnumerationAvecDonnees::kDeux {1, "test"}} }; auto copied_map = rondpoint::copie_carte(map); ASSERT_EQ(map.size(), copied_map.size()); @@ -100,10 +100,10 @@ void test_roundtrip() { for (auto i : {-1, 0, 1}) { auto nombres_signes = rondpoint::DictionnaireNombresSignes { - .petit_nombre = (int8_t)i, - .court_nombre = (int16_t)i, - .nombre_simple = (int32_t)i, - .gros_nombre = (int64_t)i, + (int8_t)i, + (int16_t)i, + (int32_t)i, + (int64_t)i, }; auto ret = rt->identique_nombres_signes(nombres_signes); @@ -115,10 +115,10 @@ void test_roundtrip() { for (auto i : {0, 1}) { auto nombres = rondpoint::DictionnaireNombres { - .petit_nombre = (uint8_t)i, - .court_nombre = (uint16_t)i, - .nombre_simple = (uint32_t)i, - .gros_nombre = (uint64_t)i, + (uint8_t)i, + (uint16_t)i, + (uint32_t)i, + (uint64_t)i, }; auto ret = rt->identique_nombres(nombres); @@ -181,21 +181,21 @@ void test_default_parameter_literals_in_record() { auto rt = rondpoint::Retourneur::init(); auto dict = rondpoint::OptionneurDictionnaire { - .i8_var = -8, - .u8_var = 8, - .i16_var = -16, - .u16_var = 0x10, - .i32_var = -32, - .u32_var = 32, - .i64_var = -64, - .u64_var = 64, - .float_var = 4.0f, - .double_var = 8.0, - .boolean_var = true, - .string_var = "default", - .list_var = std::vector{}, - .enumeration_var = rondpoint::Enumeration::kDeux, - .dictionnaire_var = std::nullopt + -8, + 8, + -16, + 0x10, + -32, + 32, + -64, + 64, + 4.0f, + 8.0, + true, + "default", + std::vector{}, + rondpoint::Enumeration::kDeux, + std::nullopt }; auto copied_dict = rt->identique_optionneur_dictionnaire(dict); ASSERT_EQ(dict.i8_var, copied_dict.i8_var); diff --git a/docs/SCAFFOLDING.md b/docs/SCAFFOLDING.md index 6c79b83..3bd8440 100644 --- a/docs/SCAFFOLDING.md +++ b/docs/SCAFFOLDING.md @@ -34,7 +34,7 @@ This file should be included once in the C++ library, and it will contain all of To ensure that the generated code is able to interface with the target C++ library, the following guidelines should be followed: -- The library should be compiled with C++20 or later. +- The library should be compiled with C++17 or later. - When exposing a struct or class, all of the members mentioned in the UDL file should be public. - For object types, all constructors mentioned in the UDL file should have a matching public constructor in the C++ library. - When exposing callback interfaces, it is recommended to not have any processing-intensive or global data modifying logic in the constructors and destructors of the backing C++ class, as due to the way uniffi internally handles callback interfaces, callback instances may be dynamically constructed multiple times during the runtime of the application. @@ -61,7 +61,7 @@ struct Handle { struct UniffiCustomTypeConverterHandle { static Handle into_custom(uint64_t val) { - Handle handle = Handle { .inner = val } // or some other more intricate logic + Handle handle{val}; // or some other more intricate logic return handle; } From c396b3b860850d6984aa4ee1621eca2fd44ee6e8 Mon Sep 17 00:00:00 2001 From: Alan George Date: Wed, 16 Sep 2026 10:18:39 -0600 Subject: [PATCH 6/6] Clarify native byte order detection --- bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp | 1 + bindgen/src/bindings/cpp/templates/rust_buf_stream.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp b/bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp index d8591e4..f3f6a41 100644 --- a/bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp +++ b/bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/bindgen/src/bindings/cpp/templates/rust_buf_stream.cpp b/bindgen/src/bindings/cpp/templates/rust_buf_stream.cpp index c2c248a..4752303 100644 --- a/bindgen/src/bindings/cpp/templates/rust_buf_stream.cpp +++ b/bindgen/src/bindings/cpp/templates/rust_buf_stream.cpp @@ -47,8 +47,9 @@ struct RustStream: std::basic_iostream { private: // Avoid platform-specific endian APIs while retaining C++17 compatibility. static bool native_byte_order_is_little_endian() { - const uint16_t value = 1; - return *reinterpret_cast(&value) == 1; + const std::uint16_t value = 1; + const auto *bytes = reinterpret_cast(&value); + return bytes[0] == 1; } RustStreamBuffer streambuf;