ICU4X
International Components for Unicode
|
ICU4X's core functionality is completely available from C++, with headers generated by Diplomat. The port is header-only; no additional C++ translation units need to be compiled to use ICU4X from C++.
The docs can be found here.
Typically C++ users can build ICU4X by building the icu_capi
Rust crate, and linking the resultant static library to their C++ application. This crate contains all of the relevant Diplomat-generated extern "C"
declarations, as well as an idiomatic C++ wrapper using these functions.
Using ICU4X in C++ is best demonstrated via these examples. For example, here's an example showing off decimal formatting in ICU4X, built with [this Makefile](Makefile).
We are still working on improving the user experience of using ICU4X from other languages. As such, this tutorial may be a bit sparse, but we are happy to answer questions on our discussions forum and help you out
After installing Rust, create a local Rust configuration for ICU4X:
Some of the keys are required by the parser, but won't be used by us.
icu_capi
supports a list of optional features:
default
enables a default set of featuresstd
[default] set this when building for a target with a Rust standard library, otherwise see belowcompiled_data
[default] to include data and enable DataProvider
-less constructorssimple_logger
[default] enable basic stdout logging of error metadata. Further loggers can be added on request.default_components
[default] activate all stable ICU4X components. For smaller builds, this can be disabled, and components can be added with features like list
.buffer_provider
for working with blob data providers (DataProvider::create_from_byte_slice()
)You can now set features by updating the features
key in Cargo.toml
:
You can now build a staticlib
with the following command:
--release
to get an optimized buildCARGO_PROFILE_RELEASE_LTO=true
to enable link-time optimizationCARGO_PROFILE_RELEASE_OPT_LEVEL="s"
to optimize for sizeYou should now have a target/release/libicu_capi.a
, ready to compile into your C++ binary.
Here's an annotated, shorter version of the decimal example:
The header files are shipped inside the crate, which Cargo has put somewhere on your system. You can find its location with
Then you can build with
C++ versions beyond C++17 are supported, as are other C++ compilers.
no_std
)Users wishing to use ICU4X on a no_std
platform will need to provide an allocator and a panic hook in order to build a linkable library. The icu_capi
crate can provide a looping panic handler, and a malloc
-backed allocator, under the looping_panic_handler
and libc_alloc
features, respectively.
This can be built the same way, with an explicitly specified --target
(in this case, thumbv7em-none-eabi
, but it can be any no_std
target)
Fallible methods return diplomat::result
, a Result type that can most commonly be converted to a std::optional
over its Ok/Err types by calling .ok()
or .err()
. Most methods either use ICU4XError
(an enum of error codes) as their error type, or std::monostate
. Further error details can be logged by enabling a logger via ICU4XLogger
, further loggers may be added on request.
The C++ headers include C headers for the underlying APIs as well, under namespace capi
, found in the .h
files. While these can be used directly, we recommend against it unless you are writing C code. These headers are not intended to be ergonomic and primarily exist for the C++ headers to use internally.
Slices are represented using std::span
if available, otherwise a simple wrapper called diplomat::span
is used.
These bindings may be customized by running diplomat-tool
directly (including replacing the types used with alternate types like mozilla::Span
), please ask on our discussions forum for more help on this.