From: "Rémi Bernon" Subject: [PATCH 1/7] widl: Generate helper macros for WinRT implementation. Message-Id: <20210222090305.557337-1-rbernon@codeweavers.com> Date: Mon, 22 Feb 2021 10:02:59 +0100 This generates additional macros to help keeping implementation simple, guarded with WIDL_USING ifdefs, like this: #ifdef WIDL_USING_WINDOWS_FOO #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_WINDOWS_FOO */ 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. Signed-off-by: Rémi Bernon --- I updated this patch with WIDL_USING macros for namespaces instead, and to use format_namespace to make them. Then I'm adding the C++ compatibility patches too, that should fix C++ compilation errors and make the C++ interfaces code generation closer to MIDL. tools/widl/header.c | 54 ++++++++++++++++++++++++++++++++++++++++++ tools/widl/typetree.c | 19 +++++++++++++++ tools/widl/widltypes.h | 1 + 3 files changed, 74 insertions(+) diff --git a/tools/widl/header.c b/tools/widl/header.c index 82aad0f11ca..95bdb8cacb8 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -48,6 +48,8 @@ static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declon static void write_apicontract_guard_start(FILE *header, const expr_t *expr); static void write_apicontract_guard_end(FILE *header, const expr_t *expr); +static void write_widl_using_macros(FILE *header, type_t *iface); + static void indent(FILE *h, int delta) { int c; @@ -604,6 +606,7 @@ static void write_type_definition(FILE *f, type_t *t, int declonly) fprintf(f, "#else\n"); write_type_left(f, &ds, NAME_C, declonly, TRUE); fprintf(f, ";\n"); + if (winrt_mode) write_widl_using_macros(f, t); fprintf(f, "#endif\n\n"); } if (contract) write_apicontract_guard_end(f, contract); @@ -1536,6 +1539,56 @@ 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 void write_widl_using_method_macros(FILE *header, const type_t *iface, const type_t *top_iface) +{ + const statement_t *stmt; + const char *name = top_iface->short_name ? top_iface->short_name : top_iface->name; + + if (type_iface_get_inherit(iface)) write_widl_using_method_macros(header, type_iface_get_inherit(iface), top_iface); + + STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) + { + const var_t *func = stmt->u.var; + const char *func_name; + + if (is_override_method(iface, top_iface, func)) continue; + if (is_callas(func->attrs)) continue; + + func_name = get_name(func); + fprintf(header, "#define %s_%s %s_%s\n", name, func_name, top_iface->c_name, func_name); + } +} + +static char *format_widl_using_macro(const type_t *type) +{ + char *name = format_namespace(type->namespace, "WIDL_USING_", "_", "", NULL); + int i = strlen(name); + if (i) name[i - 1] = 0; /* remove trailing underscore */ + for (; i > 0; --i) name[i - 1] = toupper(name[i - 1]); + return name; +} + +static void write_widl_using_macros(FILE *header, type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + const char *name = iface->short_name ? iface->short_name : iface->name; + char *macro; + + if (!strcmp(iface->name, iface->c_name)) return; + + macro = format_widl_using_macro(iface); + fprintf(header, "#ifdef %s\n", macro); + + if (uuid) fprintf(header, "#define IID_%s IID_%s\n", name, iface->c_name); + if (iface->type_type == TYPE_INTERFACE) fprintf(header, "#define %sVtbl %sVtbl\n", name, iface->c_name); + fprintf(header, "#define %s %s\n", name, iface->c_name); + + if (iface->type_type == TYPE_INTERFACE) write_widl_using_method_macros(header, iface, iface); + + fprintf(header, "#endif /* WIDL_USING_%s */\n", macro); + free(macro); +} + static void write_com_interface_end(FILE *header, type_t *iface) { int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); @@ -1608,6 +1661,7 @@ static void write_com_interface_end(FILE *header, type_t *iface) fprintf(header, "#else\n"); write_inline_wrappers(header, type, type, iface->c_name); fprintf(header, "#endif\n"); + if (winrt_mode) write_widl_using_macros(header, iface); fprintf(header, "#endif\n"); fprintf(header, "\n"); fprintf(header, "#endif\n"); diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 319dd4ae65a..8bce314018a 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -52,6 +52,7 @@ type_t *make_type(enum type_type type) t->c_name = NULL; t->signature = NULL; t->qualified_name = NULL; + t->short_name = NULL; memset(&t->details, 0, sizeof(t->details)); t->typestring_offset = 0; t->ptrdesc = 0; @@ -334,6 +335,22 @@ static char *format_parameterized_type_signature(type_t *type, typeref_list_t *p return buf; } +static char *format_parameterized_type_short_name(type_t *type, typeref_list_t *params, const char *prefix) +{ + size_t len = 0, pos = 0; + char *buf = NULL; + typeref_t *ref; + + pos += strappend(&buf, &len, pos, "%s%s", prefix, type->name); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + for (type = ref->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} + pos += strappend(&buf, &len, pos, "_%s", type->name); + } + + return buf; +} + type_t *type_new_function(var_list_t *args) { var_t *arg; @@ -1151,11 +1168,13 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t new_type->name = format_parameterized_type_name(type, params); reg_type(new_type, new_type->name, new_type->namespace, 0); new_type->c_name = format_parameterized_type_c_name(type, params, ""); + new_type->short_name = format_parameterized_type_short_name(type, params, ""); if (new_type->type_type == TYPE_DELEGATE) { new_type->details.delegate.iface = duptype(tmpl->details.delegate.iface, 0); compute_delegate_iface_names(new_type, type, params); + new_type->details.delegate.iface->short_name = format_parameterized_type_short_name(type, params, "I"); } return new_type; diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 81646cae1d1..bedba40d903 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -504,6 +504,7 @@ struct _type_t { const char *c_name; const char *signature; const char *qualified_name; + const char *short_name; unsigned int typestring_offset; unsigned int ptrdesc; /* used for complex structs */ int typelib_idx; -- 2.30.0