[PATCH v3 5/5] widl: Generate helper macros for WinRT implementation.

Rémi Bernon rbernon at codeweavers.com
Thu Sep 3 07:42:03 CDT 2020


With the previous sample idl:

    #ifdef __WIDL__
    #pragma winrt ns_prefix
    #endif

    import "wtypes.idl";

    namespace Windows {
        namespace Foo {
            [object]
            interface IFoo<T,U> { HRESULT DoFoo([in] T value, [out, retval] U *out_value); }
        }
        namespace Bar {
            [object] interface IBaz {}

            [object]
            interface IBar { HRESULT DoBar([in] Windows.Foo.IFoo<IBaz> *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 <rbernon at codeweavers.com>
---
 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




More information about the wine-devel mailing list