On 2/23/26 10:53, Daniel P. Berrangé wrote:
On Thu, Jan 08, 2026 at 02:10:27PM +0100, Paolo Bonzini wrote:
This adds two related parts of the Rust bindings:
- QAPI code generator that creates Rust structs from the JSON
description. The structs are *not* ABI compatible with the
C ones, instead they use native Rust data types.
- QObject bindings and (de)serialization support, which can be used to
convert QObjects to and from QAPI structs.
Unfortunately Rust code is not able to use visitors, other than by
creating an intermediate QObject. This is because of the different
architecture of serde vs. QAPI visitors, and because visitor's
dual-purpose functions, where the same function is used by both input and
output visitors, rely heavily on the structs using the same representation
as the visitor arguments (for example NUL-terminated strings).
The serde format implementation was co-authored by me and Marc-André.
Marc-André did all the bug fixing and integration testing.
As an example of how this would be used, the marshaling functions for
QMP commands would look like this:
Can you give more of the big picture about what follows this ? From
this example you're showing, are you suggesting that you'll be soon
moving QMP command impls from C to Rust ?
The reasons for Marc-André and I to do this was just as an exploration.
The patches show a different way to do what he had already tackled in
2022, and allow a direct comparison the relative benefits between a more
Rust-focused approach and a more direct translation of QEMU's C code.
Marc-André indeed had command implementations in Rust and that would be
an obvious next step to continue on the QAPI side. On the other hand,
the QObject part (without QAPI structs) also works as a step towards
more QOM integration, especially with respect to properties and
backends. Having a full-blown QObject implementation to move around
bools is perhaps over-engineered, but is also an easy way to make a
generic implementation that works for all QAPI types.
The block layer also needs QAPI for option parsing, so Kevin's work on
block layer bindings would also benefit from having this integration.
In other words, there is no real big picture from me other than "someone
needs to do the hard part for others": QOM, QAPI and the build system
are the three central components from which all other bindings branch
out. Zhao and Marc-André have helped a lot with this work, and they
also showed how to use these hard parts (see Zhao's vm-memory work and
Marc-André's GStreamer backend), now it's also time for others to try
and to take inspiration from Rust for improving the C side of things.
Paolo
fn qmp_marshal_query_stats(args: *mut QDict,
retp: *mut *mut QObject, errp: *mut *mut Error)
{
let qobj = unsafe { QObject::cloned_from_raw(args.cast()) };
let result = from_qobject::<StatsFilter>(qobj)
.map_err(anyhow::Error::from)
.and_then(qmp_query_stats)
.and_then(|ret|
to_qobject::<Vec<StatsResult>>(ret).map_err(anyhow::Error::from));
match qmp_marshal_query_stats_rs(qobj) {
Ok(ret) => unsafe { *retp = ret.into_raw(); },
Err(e) => unsafe { crate::Error::from(e).propagate(errp) },
}
}
With regards,
Daniel