From: Zhao Liu <zhao1.liu@intel.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org, marcandre.lureau@redhat.com,
qemu-rust@nongnu.org, armbru@redhat.com, mkletzan@redhat.com
Subject: Re: [PATCH preview 0/3] reviving minimal QAPI generation from 2021
Date: Wed, 11 Jun 2025 16:13:49 +0800 [thread overview]
Message-ID: <aEk6vdosWZgyQGXD@intel.com> (raw)
In-Reply-To: <20250605101124.367270-1-pbonzini@redhat.com>
On Thu, Jun 05, 2025 at 12:11:21PM +0200, Paolo Bonzini wrote:
> Date: Thu, 5 Jun 2025 12:11:21 +0200
> From: Paolo Bonzini <pbonzini@redhat.com>
> Subject: [PATCH preview 0/3] reviving minimal QAPI generation from 2021
> X-Mailer: git-send-email 2.49.0
>
> This is just an extremely minimal extraction from the patches at
> https://patchew.org/QEMU/20210907121943.3498701-1-marcandre.lureau@redhat.com/,
> limited to generating structs and enums from the QAPI schema.
> It does not include them in any crate and does not compile them.
>
> While I'm not going to work on this, I was curious how much work it
> was to produce *some* kind of Rust QAPI struct, which could be a first
> step towards using serde as an interface to C visitors, like this:
>
> trait QapiType: FreeForeign {
> unsafe fn visit(v: bindings::Visitor, name: *const c_char, obj: *mut <Self as FreeForeign>::Foreign, errp: *mut *mut bindings::Error);
> }
>
> fn to_c<T: QAPIType>(obj: &T) -> *mut <T as FreeForeign>::Foreign {
> let mut ptr = libc::calloc(...);
> let mut ser = QapiSerializer::<T>::new(ptr);
> obj.serialize(&mut ser).unwrap();
> ptr.cast()
> }
>
> unsafe fn from_c<T: QAPIType>(obj: *const <T as FreeForeign>::Foreign) -> T {
> let mut de = QapiDeserializer::new(T::visit, obj as *const c_void);
> let value = de::Deserialize::deserialize(&mut de).unwrap();
> de.end().unwrap();
> value
> }
>
> /* Generated code below: */
>
> impl QapiType for UefiVariable {
> unsafe fn visit(v: bindings::Visitor, name: *const c_char, obj: *mut bindings::UefiVariable, errp: *mut *mut bindings::Error) {
> unsafe extern "C" visit_type_DumpGuestMemoryFormat(v: bindings::Visitor, name: *const c_char, obj: *mut bindings::UefiVariable, errp: *mut *mut bindings::Error) {
> unsafe { visit_type_DumpGuestMemoryFormat(v, name, obj, errp); }
> }
> }
>
> impl FreeForeign for UefiVariable {
> type Foreign = bindings::UefiVariable;
My question seems to be different from Marc-André's...
As patch 3 did, qapi will generate Rust types:
- char* is mapped to String, scalars to there corresponding Rust types
- enums are simply aliased from FFI
- has_foo/foo members are mapped to Option<T>
- lists are represented as Vec<T>
- structures have Rust versions, with To/From FFI conversions
It seems we still need some raw bindings (generated by bindgen) as the
`type Foreign`, and then implement Foreign traits for the Rust
structures generated by this patch.
For this example, UefiVariable is generated by qapi (patch 3) and
bindings::UefiVariable is generated by bindgen. Ah! I feel I'm wrong,
could you please correct me?
Thanks,
Zhao
> unsafe fn free_foreign(p: *mut bindings::UefiVariable) {
> unsafe extern "C" qapi_free_UefiVariable(p: *mut bindings::UefiVariable);
> unsafe { qapi_free_UefiVariable(p); }
> }
> }
>
> impl CloneToForeign for UefiVariable {
> fn clone_to_foreign(&self) -> OwnedPointer<Self> {
> OwnedPointer::new(qapi::to_c(self))
> }
> }
>
> impl FromForeign for UefiVariable {
> unsafe fn cloned_from_foreign(obj: *const bindings::UefiVariable) -> Self {
> qapi::from_c(obj)
> }
> }
>
> The FFI types could be generated by qapi-gen, as in Marc-André's
> proposal, or from bindgen.
>
> I am not sure what approach is better---whether to use serde or to
> automatically generate the marshaling and unmarshaling code; and whether
> to use bindgen or generate C-compatible FFI types---but it made sense,
> from the point of view of extracting "some" code from Marc-André's
> proof of concept and enticing other people, :) to start from high-level
> types.
>
next prev parent reply other threads:[~2025-06-11 7:52 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-05 10:11 [PATCH preview 0/3] reviving minimal QAPI generation from 2021 Paolo Bonzini
2025-06-05 10:11 ` [PATCH 1/3] rust: make TryFrom macro more resilient Paolo Bonzini
2025-06-10 13:26 ` Marc-André Lureau
2025-06-10 15:52 ` Zhao Liu
2025-06-05 10:11 ` [PATCH 2/3] scripts/qapi: add QAPISchemaIfCond.rsgen() Paolo Bonzini
2025-06-10 13:33 ` Marc-André Lureau
2025-06-05 10:11 ` [PATCH 3/3] scripts/qapi: generate high-level Rust bindings Paolo Bonzini
2025-06-11 8:09 ` Zhao Liu
2025-06-10 13:53 ` [PATCH preview 0/3] reviving minimal QAPI generation from 2021 Marc-André Lureau
2025-06-10 16:10 ` Paolo Bonzini
2025-06-11 8:13 ` Zhao Liu [this message]
2025-06-11 8:57 ` Paolo Bonzini
2025-06-12 10:24 ` Paolo Bonzini
2025-06-13 5:57 ` Zhao Liu
2025-06-16 8:55 ` Paolo Bonzini
2025-06-18 14:25 ` Markus Armbruster
2025-06-18 17:36 ` Paolo Bonzini
2025-06-23 12:52 ` Markus Armbruster
2025-07-02 19:09 ` Paolo Bonzini
2025-06-17 7:49 ` Markus Armbruster
2025-06-18 8:27 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aEk6vdosWZgyQGXD@intel.com \
--to=zhao1.liu@intel.com \
--cc=armbru@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=mkletzan@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-rust@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.