On Mon Nov 18 11:02:49 2024 +0000, Rémi Bernon wrote:
I'm not sure what you mean by `QITAB`, but implementing QueryInterface is just one small piece of macro usage. The main source is probably the higher level macro that generates all the boilerplates (ie: vtables and forwards for every implemented interfaces of a given class).
Here's a rough example of what I meant. Take `IWineForceFeedbackEffectImpl` for instance:
``` interface IWineForceFeedbackEffectImpl : IInspectable requires Windows.Gaming.Input.ForceFeedback.IForceFeedbackEffect ```
From this, widl would create something like (using unmangled interface names for clarity):
``` #define INTERFACES_IWineForceFeedbackEffectImpl(type, ...) \ const static QITAB QITAB_IWineForceFeedbackEffectImpl[] = \ { \ {&IID_IInspectable, offsetof( type, IWineForceFeedbackEffectImpl_iface )}, \ {&IID_IForceFeedbackEffect, offsetof( type, IForceFeedbackEffect_iface )}, \ __VA_ARGS__ \ }; ```
With the following definitions in `wine/comimpl.h`:
``` #define QITAB_ENTRY(type, X) {&IID##_x, offsetof(type, X##_face)}, #define QITAB_END {NULL, 0} ... #define IUNKNOWN_IMPL_QUERY_INTERFACE_( type, name, impl_from, log ) \ static HRESULT WINAPI type ## _QueryInterface( name *iface, REFIID iid, void **out ) \ { \ struct type *object = impl_from( iface ); \ HRESULT hres; TRACE( "object %p, iid %s, out %p.\n", object, debugstr_guid(iid), out ); \ hres = QISearch(object, QITAB##_name, iid, out); if (hres == E_NOINTERFACE) (log)( "%s not implemented, returning E_NOINTERFACE.", debugstr_guid(iid)); return hres; } ```
[This line](https://gitlab.winehq.org/wine/wine/-/merge_requests/6207/diffs#1645e0df6b8e...) in `force_feedback.c` could be written as
``` INTERFACE_IMPL_OUTER_IWineForceFeedbackEffectImpl( effect, QITAB_ENTRY(IAgileObject), QITAB_END, FIXME ); ```
Which would then expand to the `QITAB` array above + remaining macros. The idea is that this would replace all `QUERY_INTERFACE{S}{_OPT}` macros with one `QITAB` array, simplify `QueryInterface`'s code, and also provide a convenient way to implement `GetIids`, if we ever need to in the future (as we now have an array of all known IIDs for the object). `QISearch` is already in kernelbase, so this shouldn't add any new dependencies if I understand correctly. It also makes it mandatory for the implementation to implement the interfaces annotated with `requires`. (I do realize now that it doesn't really reduce macro usage all that much, but I'd still be interested in knowing what you think about this :P)