From: "Rémi Bernon" Subject: [PATCH v3 5/5] widl: Generate helper macros for WinRT implementation. Message-Id: <20200903124203.2460412-5-rbernon@codeweavers.com> Date: Thu, 3 Sep 2020 14:42:03 +0200 In-Reply-To: <20200903124203.2460412-1-rbernon@codeweavers.com> References: <20200903124203.2460412-1-rbernon@codeweavers.com> With the previous sample idl: #ifdef __WIDL__ #pragma winrt ns_prefix #endif import "wtypes.idl"; namespace Windows { namespace Foo { [object] interface IFoo { HRESULT DoFoo([in] T value, [out, retval] U *out_value); } } namespace Bar { [object] interface IBaz {} [object] interface IBar { HRESULT DoBar([in] Windows.Foo.IFoo *foo); } } } This generates, in WinRT mode, these additional macros to help keeping implementation simple (and similarly for other interfaces): #ifdef WIDL_USING_CWINDOWS_CFOO_CIFOO #define IFooVtbl __x_ABI_CWindows_CFoo_CIFooVtbl #define IFoo __x_ABI_CWindows_CFoo_CIFoo #define IFoo_DoFoo __x_ABI_CWindows_CFoo_CIFoo_DoFoo #endif /* WIDL_USING_CWINDOWS_CFOO_CIFOO */ Implementation files can define the desired WIDL_USING preprocessor macros before including the header, and then implement or use the interface methods with the simple non-prefixed names instead: #define COBJMACROS #define WIDL_USING_CWINDOWS_CFOO_CIFOO #define WIDL_USING_CWINDOWS_CBAR_CIBAZ #define WIDL_USING_CWINDOWS_CBAR_CIBAR #include "windows.foo.h" struct bar { IBar IBar_iface; IBaz *baz; }; static struct bar *impl_from_IBar(IBar *iface) { return CONTAINING_RECORD(iface, struct bar, IBar_iface); } static HRESULT WINAPI bar_DoBar(IBar *iface, IFoo *foo) { struct bar *This = impl_from_IBar(iface); return IFoo_DoFoo(foo, This->baz, (void **)&This->baz); } static const IBarVtbl bar_vtbl = { bar_DoBar, }; Signed-off-by: Rémi Bernon --- tools/widl/header.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tools/widl/header.c b/tools/widl/header.c index fcc73169d00..6b86f0a95fe 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1460,12 +1460,65 @@ static void write_com_interface_start(FILE *header, const type_t *iface) fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : ""); } +static char *get_winrt_guard_macro(type_t *iface) +{ + const char *tmp = (char *)iface->c_name; + char *macro; + int i; + + if (!strncmp(tmp, "__x", 3)) tmp += 3; + if (!strncmp(tmp, "_ABI_", 5)) tmp += 5; + macro = xstrdup(tmp); + for (i = strlen(macro); i > 0; --i) macro[i - 1] = toupper(macro[i - 1]); + + return macro; +} + +static void write_widl_using_method_macros(FILE *header, const type_t *iface, const type_t *child) +{ + const statement_t *stmt; + + if (type_iface_get_inherit(iface)) write_widl_using_method_macros(header, type_iface_get_inherit(iface), child); + + STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) + { + const var_t *func = stmt->u.var; + + if (is_override_method(iface, child, func)) continue; + + if (!is_callas(func->attrs)) + fprintf(header, "#define %s_%s %s_%s\n", child->name, get_name(func), child->c_name, get_name(func)); + } +} + +static void write_widl_using_macros(FILE *header, type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + char *macro; + + if (!strcmp(iface->name, iface->c_name)) return; + + macro = get_winrt_guard_macro(iface); + fprintf(header, "#ifdef WIDL_USING_%s\n", macro); + + if (uuid) fprintf(header, "#define IID_%s IID_%s\n", iface->name, iface->c_name); + fprintf(header, "#define %sVtbl %sVtbl\n", iface->name, iface->c_name); + fprintf(header, "#define %s %s\n", iface->name, iface->c_name); + + write_widl_using_method_macros(header, iface, iface); + + fprintf(header, "#endif /* WIDL_USING_%s */\n\n", macro); + free(macro); +} + static void write_com_interface_end(FILE *header, type_t *iface) { int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); type_t *type; + if (winrt_mode) write_widl_using_macros(header, iface); + if (uuid) write_guid(header, dispinterface ? "DIID" : "IID", iface->c_name, uuid); -- 2.28.0