Warning: losely related brain dump ahead. introspect.py's purpose is providing query-qmp-schema with the data it needs to built its response, which is a JSON object conforming to ['SchemaInfo'].
Stupidest solution that could possibly work: have this module generate a C string holding the (JSON text) response. Since a QMP command handler returns a QAPI object, not the response string, this becomes: schema | | qapi-gen.py v C string -------------------------------------------------- | | qobject_from_json() v QObject qmp_query_qmp_schema() | | QObject input visitor v SchemaInfoList -------------------------------------------------- | | QObject output visitor generated wrapper v QObject -------------------------------------------------- | | qobject_to_json() QMP core v C string Meh. So many pointless conversions. Shortcut: 'gen' false lets us cut out two: schema | | qapi-gen.py v C string -------------------------------------------------- | | qobject_from_json() qmp_query_qmp_schema() v QObject -------------------------------------------------- | | qobject_to_json() QMP core v C string Less work for handwritten qmp_query_qmp_schema(); it's now a one-liner. This is the initial version (commit 39a1815816). Commit 7d0f982bfb replaced the generated C string by a QLitObject: schema | | qapi-gen.py v QLitObj -------------------------------------------------- | | qobject_from_qlit() qmp_query_qmp_schema() v QObject -------------------------------------------------- | | qobject_to_json() QMP core v C string The commit message claims the QLitObj is "easier to deal with". I doubt it. The conversion to QObject is a one-liner before and after. Neither form is hard to generate (example appended). QLitObj takes more memory: ~360KiB, mostly .data (unnecessarily?), wheras the C string is ~150KiB .text. Of course, both are dwarved many times over by QObject: 12.4MiB. Gross. However, to actually work with the introspection data in C, we'd want it as SchemaInfoList. I have a few uses for introspection data in mind, and I definitely won't code them taking QObject input. SchemaInfoList is one visitor away from QObject, so no big deal. But what if we generated SchemaInfoList directly? We'd have: schema | | qapi-gen.py v SchemaInfoList -------------------------------------------------- | | QObject output visitor generated wrapper v QObject -------------------------------------------------- | | qobject_to_json() QMP core v C string At ~480KiB, SchemaInfoList is less compact than QLitObj (let alone the C string). It should go entirely into .text, though. I don't think generating SchemaInfoList would be particularly hard. Just work. Bigger fish to fry, I guess. But getting the idea out can't hurt. Example: BlockdevOptionsFile { 'struct': 'BlockdevOptionsFile', 'data': { 'filename': 'str', '*pr-manager': 'str', '*locking': 'OnOffAuto', '*aio': 'BlockdevAioOptions', '*drop-cache': {'type': 'bool', 'if': 'defined(CONFIG_LINUX)'}, '*x-check-cache-dropped': 'bool' }, 'features': [ { 'name': 'dynamic-auto-read-only', 'if': 'defined(CONFIG_POSIX)' } ] } Generated QLitObj: /* "267" = BlockdevOptionsFile */ QLIT_QDICT(((QLitDictEntry[]) { { "features", QLIT_QLIST(((QLitObject[]) { #if defined(CONFIG_POSIX) QLIT_QSTR("dynamic-auto-read-only"), #endif /* defined(CONFIG_POSIX) */ {} })), }, { "members", QLIT_QLIST(((QLitObject[]) { QLIT_QDICT(((QLitDictEntry[]) { { "name", QLIT_QSTR("filename"), }, { "type", QLIT_QSTR("str"), }, {} })), QLIT_QDICT(((QLitDictEntry[]) { { "default", QLIT_QNULL, }, { "name", QLIT_QSTR("pr-manager"), }, { "type", QLIT_QSTR("str"), }, {} })), QLIT_QDICT(((QLitDictEntry[]) { { "default", QLIT_QNULL, }, { "name", QLIT_QSTR("locking"), }, { "type", QLIT_QSTR("412"), }, {} })), QLIT_QDICT(((QLitDictEntry[]) { { "default", QLIT_QNULL, }, { "name", QLIT_QSTR("aio"), }, { "type", QLIT_QSTR("413"), }, {} })), #if defined(CONFIG_LINUX) QLIT_QDICT(((QLitDictEntry[]) { { "default", QLIT_QNULL, }, { "name", QLIT_QSTR("drop-cache"), }, { "type", QLIT_QSTR("bool"), }, {} })), #endif /* defined(CONFIG_LINUX) */ QLIT_QDICT(((QLitDictEntry[]) { { "default", QLIT_QNULL, }, { "name", QLIT_QSTR("x-check-cache-dropped"), }, { "type", QLIT_QSTR("bool"), }, {} })), {} })), }, { "meta-type", QLIT_QSTR("object"), }, { "name", QLIT_QSTR("267"), }, {} })), Generated C string would look like this: "{\"features\": [" #if defined(CONFIG_POSIX) "\"dynamic-auto-read-only\"" #endif /* defined(CONFIG_POSIX) */ "], " "\"members\": [" "{\"name\": \"filename\", \"type\": \"str\"}, " "{\"name\": \"pr-manager\", \"default\": null, \"type\": \"str\"}, " "{\"name\": \"locking\", \"default\": null, \"type\": \"412\"}, " "{\"name\": \"aio\", \"default\": null, \"type\": \"413\"}, " #if defined(CONFIG_LINUX) "{\"name\": \"drop-cache\", \"default\": null, \"type\": \"bool\"}, " #endif /* defined(CONFIG_LINUX) */ "{\"name\": \"x-check-cache-dropped\", \"default\": null, \"type\": \"bool\"}" "], " "\"meta-type\": \"object\", " "\"name\": \"267\"" "}"