swig: replace hand-written accessor wrappers with auto-generated #defines#3304
Merged
igaw merged 1 commit intolinux-nvme:masterfrom Apr 22, 2026
Merged
Conversation
…ines SWIG generates accessor names as libnvme_STRUCT_MEMBER_get/set() but libnvme exports them as libnvme_STRUCT_get/set_MEMBER(). Previously nvme.i bridged this gap with ~35 hand-written C wrapper functions (~130 lines of boilerplate) that had to be updated manually whenever new accessors were added to the library. Add generate-swig-accessors.py, a post-processing script that reads the accessor header files produced by generate-accessors.py (accessors.h and accessors-fabrics.h, covering both common and fabrics structs) and emits nvme-swig-accessors.i containing one #define per accessor: #define libnvme_ctrl_name_get libnvme_ctrl_get_name Parsing the .h files (not the .ld version scripts) ensures the output is always in sync even before the .ld section labels are manually bumped. Object-like macros are used rather than function-like macros since the call arguments follow naturally after macro expansion. Add a new update-swig-accessors run_target in meson.build and extend the update-accessors alias to include it. Replace the hand-written wrapper blocks in nvme.i with %include "nvme-swig-accessors.i". The four bridges that cannot be auto-generated (virtual member names or !accessors:none annotations) are kept as #defines in a single block next to the %include. Signed-off-by: Martin Belanger <[email protected]> Assisted-by: Claude Sonnet 4.6 <[email protected]>
igaw
reviewed
Apr 22, 2026
| #define libnvme_subsystem_host_get libnvme_subsystem_get_host | ||
| #define libnvme_ctrl_state_get libnvme_ctrl_get_state | ||
| #define libnvme_ctrl_subsystem_get libnvme_ctrl_get_subsystem | ||
| #define libnvme_ctrl_address_get libnvme_ctrl_get_traddr |
Collaborator
There was a problem hiding this comment.
I am trying to figure out if the traddr vs address name is going to bite us.
Author
There was a problem hiding this comment.
From what I can tell just looking at struct libnvme_ctrl (private.h, line 264), address and traddr are not the same thing. Or are they?
Collaborator
There was a problem hiding this comment.
address got renamed to traddr to match with the kernel argument names. I suppose we should remove address from the Python binding.
Collaborator
|
Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
swig: auto-generate #define bridges for accessors
SWIG uses a naming convention (
libnvme_STRUCT_MEMBER_get/set) that differs from the libnvme C API convention (libnvme_STRUCT_get/set_MEMBER). Until now this mismatch was papered over by ~35 hand-written C wrapper functions insidenvme.i— one thin shim per accessor that did nothing but call the real function.This commit replaces all those shims with automatically generated C preprocessor
#defineobject-like macros. Because the macros have no parameter list, the arguments flow through naturally, so no wrapper function body is needed at all.What changed
New script:
libnvme/tools/generator/generate-swig-accessors.pyPost-processing step that reads
accessors.handaccessors-fabrics.h(already kept up to date bygenerate-accessors.py) and emitslibnvme/libnvme/nvme-swig-accessors.i. It uses a non-greedy regex to split each accessor name at the first_get_/_set_occurrence so that multi-word member names (e.g.dhchap_host_key) and long struct prefixes (e.g.libnvmf_discovery_args) are handled correctly. Output is only rewritten when the content changes, avoiding spurious mtime updates.Updated:
libnvme/tools/generator/meson.buildupdate-swig-accessorsrun-target that invokes the new script.update-accessorsalias so thatmeson compile -C <build-dir> update-accessorsregenerates all three artefact sets in one shot.New generated file:
libnvme/libnvme/nvme-swig-accessors.iContains one
#defineper accessor for every struct annotated inprivate.handprivate-fabrics.h, grouped by struct and with the third column vertically aligned within each group for readability.Updated:
libnvme/libnvme/nvme.iAdded
%include "nvme-swig-accessors.i"(alongside the existing%include "exception.i") so SWIG picks up all the bridges automatically.Removed all four hand-written wrapper
%{ %}blocks (host, subsystem, ctrl, ns) — 168 lines deleted.Kept four
#definebridges that cannot be auto-generated (virtual Python property names or!accessors:noneannotations), consolidated into the main%{ %}preamble with a comment explaining why each one exists:Result
New accessors added to libnvme (via
private.hannotations) now automatically appear in the Python bindings after runningmeson compile -C <build-dir> update-accessors— zero manual maintenance ofnvme.irequired.