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 rbernon@codeweavers.com ---
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;
To windows.foundation.collections.idl.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/Makefile.in | 1 + include/windows.foundation.collections.idl | 74 ++++++++++++++++++++++ include/windows.foundation.idl | 45 +------------ 3 files changed, 76 insertions(+), 44 deletions(-) create mode 100644 include/windows.foundation.collections.idl
diff --git a/include/Makefile.in b/include/Makefile.in index c1efee700fa..6c16e01a271 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -746,6 +746,7 @@ SOURCES = \ wincrypt.h \ windef.h \ windns.h \ + windows.foundation.collections.idl \ windows.foundation.idl \ windows.h \ windows.media.speechsynthesis.idl \ diff --git a/include/windows.foundation.collections.idl b/include/windows.foundation.collections.idl new file mode 100644 index 00000000000..9f7a59ab907 --- /dev/null +++ b/include/windows.foundation.collections.idl @@ -0,0 +1,74 @@ +/* + * Copyright 2021 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +import "inspectable.idl"; +/* import "asyncinfo.idl"; */ +import "windowscontracts.idl"; +/* import "eventtoken.idl"; */ + +namespace Windows { + namespace Foundation { +#ifdef __WIDL__ + [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(9de1c535-6ae1-11e0-84e1-18a905bcc53f) + ] + delegate HRESULT EventHandler<T>([in] IInspectable *sender, [in] T args); + + namespace Collections + { + [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(6a79e863-4300-459a-9966-cbb660963ee1) + ] + interface IIterator<T> : IInspectable + { + [propget] HRESULT Current([out, retval] T *value); + [propget] HRESULT HasCurrent([out, retval] BOOL *value); + HRESULT MoveNext([out, retval] BOOL *value); + HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value); + } + + [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(faa585ea-6214-4217-afda-7f46de5869b3) + ] + interface IIterable<T> : IInspectable + { + HRESULT First([out, retval] Windows.Foundation.Collections.IIterator<T> **value); + } + + [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56) + ] + interface IVectorView<T> : IInspectable + { + HRESULT GetAt([in] ULONG index, [out, retval] T *value); + [propget] HRESULT Size([out, retval] ULONG *value); + HRESULT IndexOf([in, optional] T element, [out] ULONG *index, [out, retval] BOOLEAN *value); + HRESULT GetMany([in] ULONG start_index, [out] T *items, [out, retval] ULONG *value); + } + } +#endif + } +} diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index bb0fafcab77..3c60278cf05 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -25,6 +25,7 @@ import "inspectable.idl"; import "windowscontracts.idl"; /* import "eventtoken.idl"; */ /* import "ivectorchangedeventargs.idl"; */ +import "windows.foundation.collections.idl";
namespace Windows { namespace Foundation { @@ -111,49 +112,5 @@ namespace Windows { { HRESULT ToString([out, retval] HSTRING *value); } - -#ifdef __WIDL__ - [ - contract(Windows.Foundation.FoundationContract, 1.0), - uuid(9de1c535-6ae1-11e0-84e1-18a905bcc53f) - ] - delegate HRESULT EventHandler<T>([in] IInspectable *sender, [in] T args); - - namespace Collections - { - [ - contract(Windows.Foundation.FoundationContract, 1.0), - uuid(6a79e863-4300-459a-9966-cbb660963ee1) - ] - interface IIterator<T> : IInspectable - { - [propget] HRESULT Current([out, retval] T *value); - [propget] HRESULT HasCurrent([out, retval] BOOL *value); - HRESULT MoveNext([out, retval] BOOL *value); - HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value); - } - - [ - contract(Windows.Foundation.FoundationContract, 1.0), - uuid(faa585ea-6214-4217-afda-7f46de5869b3) - ] - interface IIterable<T> : IInspectable - { - HRESULT First([out, retval] Windows.Foundation.Collections.IIterator<T> **value); - } - - [ - contract(Windows.Foundation.FoundationContract, 1.0), - uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56) - ] - interface IVectorView<T> : IInspectable - { - HRESULT GetAt([in] ULONG index, [out, retval] T *value); - [propget] HRESULT Size([out, retval] ULONG *value); - HRESULT IndexOf([in, optional] T element, [out] ULONG *index, [out, retval] BOOLEAN *value); - HRESULT GetMany([in] ULONG start_index, [out] T *items, [out, retval] ULONG *value); - } - } -#endif } }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.foundation.collections.idl | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/include/windows.foundation.collections.idl b/include/windows.foundation.collections.idl index 9f7a59ab907..cf47adfa7e4 100644 --- a/include/windows.foundation.collections.idl +++ b/include/windows.foundation.collections.idl @@ -27,6 +27,19 @@ import "windowscontracts.idl";
namespace Windows { namespace Foundation { + +cpp_quote("#ifdef __cplusplus") +cpp_quote("} /* extern "C" */") +cpp_quote("namespace ABI { namespace Windows { namespace Foundation { namespace Internal {") +cpp_quote("template <class T> struct GetAbiType { typedef T type; };") +cpp_quote("template <class T> struct GetLogicalType { typedef T type; };") +cpp_quote("template <class L, class A> struct AggregateType {};") +cpp_quote("template <class L, class A> struct GetAbiType<AggregateType<L, A>> { typedef A type; };") +cpp_quote("template <class L, class A> struct GetLogicalType<AggregateType<L, A>> { typedef L type; };") +cpp_quote("}}}}") +cpp_quote("extern "C" {") +cpp_quote("#endif") + #ifdef __WIDL__ [ contract(Windows.Foundation.FoundationContract, 1.0),
Based on a patch from Steve Lhomme.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 45 +++++++++++++++++++++++++++++++++++++++++++ tools/widl/typetree.c | 5 +++++ 2 files changed, 50 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 95bdb8cacb8..4e3b1cb6cf3 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -125,6 +125,25 @@ unsigned int get_attrv(const attr_list_t *list, enum attr_type t) return 0; }
+static char *format_parameterized_type_args(const type_t *type, const char *prefix, const char *suffix) +{ + typeref_list_t *params; + typeref_t *ref; + size_t len = 0, pos = 0; + char *buf = NULL; + + params = type->details.parameterized.params; + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + assert(ref->type->type_type != TYPE_POINTER); + pos += strappend(&buf, &len, pos, "%s%s%s", prefix, ref->type->name, suffix); + if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ", "); + } + + if (!buf) return xstrdup(""); + return buf; +} + static void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid) { if (!uuid) return; @@ -1477,6 +1496,30 @@ static void write_function_proto(FILE *header, const type_t *iface, const var_t fprintf(header, ");\n\n"); }
+static void write_parameterized_type_forward(FILE *header, type_t *type) +{ + type_t *iface = type->details.parameterized.type; + char *args; + + if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + + fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n"); + write_namespace_start(header, type->namespace); + + args = format_parameterized_type_args(type, "class ", ""); + write_line(header, 0, "template <%s>", args); + write_line(header, 0, "struct %s_impl;\n", iface->name); + + write_line(header, 0, "template <%s>", args); + free(args); + args = format_parameterized_type_args(type, "", ""); + write_line(header, 0, "struct %s : %s_impl<%s> {};", iface->name, iface->name, args); + free(args); + + write_namespace_end(header, type->namespace); + fprintf(header, "#endif\n\n" ); +} + static void write_forward(FILE *header, type_t *iface) { fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->c_name); @@ -1872,6 +1915,8 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts) write_coclass_forward(header, stmt->u.type); else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) write_runtimeclass_forward(header, stmt->u.type); + else if (type_get_type(stmt->u.type) == TYPE_PARAMETERIZED_TYPE) + write_parameterized_type_forward(header, stmt->u.type); break; case STMT_TYPEREF: case STMT_IMPORTLIB: diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 8bce314018a..e16b7713e91 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -929,6 +929,8 @@ type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, ty iface->details.iface->async_iface = NULL; iface->details.iface->requires = requires;
+ iface->name = type->name; + type->defined = TRUE; return type; } @@ -969,6 +971,9 @@ type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, sta iface->details.iface->async_iface = NULL; iface->details.iface->requires = NULL;
+ delegate->name = type->name; + compute_delegate_iface_names(delegate, type, type->details.parameterized.params); + type->defined = TRUE; return type; }
Based on a patch from Steve Lhomme.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 75 +++++++++++++++++++++++++++++++++++++++++-- tools/widl/typetree.h | 8 +++++ 2 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 4e3b1cb6cf3..aad31e7ba4e 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -343,6 +343,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i { type_t *t = ds->type; const char *name; + char *args;
if (!h) return;
@@ -509,9 +510,19 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i else write_type_left(h, ds, name_type, declonly, write_callconv); break; } - case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: + { + type_t *iface = type_parameterized_type_get_real_type(t); + if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + args = format_parameterized_type_args(t, "", "_logical"); + fprintf(h, "%s<%s>", iface->name, args); + free(args); + break; + } case TYPE_PARAMETER: + fprintf(h, "%s_abi", t->name); + break; + case TYPE_APICONTRACT: /* shouldn't be here */ assert(0); break; @@ -578,10 +589,10 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_INTERFACE: case TYPE_RUNTIMECLASS: case TYPE_DELEGATE: - break; - case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: case TYPE_PARAMETER: + break; + case TYPE_APICONTRACT: /* not supposed to be here */ assert(0); break; @@ -1520,6 +1531,58 @@ static void write_parameterized_type_forward(FILE *header, type_t *type) fprintf(header, "#endif\n\n" ); }
+static void write_parameterized_implementation(FILE *header, type_t *type, int declonly) +{ + const statement_t *stmt; + typeref_list_t *params = params = type->details.parameterized.params; + typeref_t *ref; + type_t *iface = type->details.parameterized.type, *base; + char *args = NULL; + + fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n"); + write_line(header, 0, "} /* extern "C" */"); + write_namespace_start(header, type->namespace); + + if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + base = type_iface_get_inherit(iface); + + args = format_parameterized_type_args(type, "class ", ""); + write_line(header, 0, "template <%s>", args); + free(args); + write_line(header, 0, "struct %s_impl%s", iface->name, base ? strmake(" : %s", base->name) : ""); + write_line(header, 0, "{"); + + write_line(header, 1, "private:"); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + write_line(header, 0, "typedef typename Windows::Foundation::Internal::GetAbiType<%s>::type %s_abi;", ref->type->name, ref->type->name); + write_line(header, 0, "typedef typename Windows::Foundation::Internal::GetLogicalType<%s>::type %s_logical;", ref->type->name, ref->type->name); + } + indentation -= 1; + + write_line(header, 1, "public:"); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + write_line(header, 0, "typedef %s %s_complex;", ref->type->name, ref->type->name); + + STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) + { + const var_t *func = stmt->u.var; + if (is_callas(func->attrs)) continue; + indent(header, 1); + fprintf(header, "virtual "); + write_type_decl_left(header, &func->declspec); + fprintf(header, " %s(", get_name(func)); + write_args(header, type_function_get_args(func->declspec.type), NULL, 0, 0, NAME_DEFAULT); + fprintf(header, ") = 0;\n"); + indentation -= 1; + } + write_line(header, -1, "};"); + + write_namespace_end(header, type->namespace); + write_line(header, 0, "extern "C" {"); + write_line(header, 0, "#endif\n"); +} + static void write_forward(FILE *header, type_t *iface) { fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->c_name); @@ -1978,6 +2041,12 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons write_runtimeclass(header, stmt->u.type); else if (type_get_type(stmt->u.type) != TYPE_PARAMETERIZED_TYPE) write_type_definition(header, stmt->u.type, stmt->declonly); + else + { + is_object_interface++; + write_parameterized_implementation(header, stmt->u.type, stmt->declonly); + is_object_interface--; + } break; case STMT_TYPEREF: /* FIXME: shouldn't write out forward declarations for undefined diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 805e96a9305..0b7cd385cc2 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -96,6 +96,14 @@ static inline type_t *type_get_real_type(const type_t *type) return (type_t *)type; }
+static inline type_t *type_parameterized_type_get_real_type(const type_t *type) +{ + if (type->type_type == TYPE_PARAMETERIZED_TYPE) + return type_parameterized_type_get_real_type(type->details.parameterized.type); + else + return (type_t *)type; +} + static inline enum type_type type_get_type(const type_t *type) { return type_get_type_detect_alias(type_get_real_type(type));
Based on a patch from Steve Lhomme.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 21 +++++++++++------ tools/widl/typetree.c | 52 ++++++++++++++++++++++++++++++++++++++---- tools/widl/typetree.h | 6 +++++ tools/widl/widltypes.h | 1 + 4 files changed, 68 insertions(+), 12 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index aad31e7ba4e..b8fe3c1c445 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1591,10 +1591,12 @@ static void write_forward(FILE *header, type_t *iface) fprintf(header, "#ifdef __cplusplus\n"); if (iface->namespace && !is_global_namespace(iface->namespace)) fprintf(header, "#define %s %s\n", iface->c_name, iface->qualified_name); - write_namespace_start(header, iface->namespace); - if (strchr(iface->name, '<')) write_line(header, 0, "template<> struct %s;", iface->name); - else write_line(header, 0, "interface %s;", iface->name); - write_namespace_end(header, iface->namespace); + if (!iface->impl_name) + { + write_namespace_start(header, iface->namespace); + write_line(header, 0, "interface %s;", iface->name); + write_namespace_end(header, iface->namespace); + } fprintf(header, "#endif /* __cplusplus */\n"); fprintf(header, "#endif\n\n" ); } @@ -1720,7 +1722,12 @@ static void write_com_interface_end(FILE *header, type_t *iface) if (strchr(iface->name, '<')) fprintf(header, "template<> struct "); else fprintf(header, "interface "); } - if (type_iface_get_inherit(iface)) + if (iface->impl_name) + { + fprintf(header, "%s : %s\n", iface->name, iface->impl_name); + write_line(header, 1, "{"); + } + else if (type_iface_get_inherit(iface)) { fprintf(header, "%s : public %s\n", iface->name, type_iface_get_inherit(iface)->name); @@ -1734,9 +1741,9 @@ static void write_com_interface_end(FILE *header, type_t *iface) } /* dispinterfaces don't have real functions, so don't write C++ functions for * them */ - if (!dispinterface) + if (!dispinterface && !iface->impl_name) write_cpp_method_def(header, iface); - if (!type_iface_get_inherit(iface)) + if (!type_iface_get_inherit(iface) && !iface->impl_name) write_line(header, 0, "END_INTERFACE\n"); write_line(header, -1, "};"); if (!is_global_namespace(iface->namespace)) { diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index e16b7713e91..090a16ba182 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -53,6 +53,7 @@ type_t *make_type(enum type_type type) t->signature = NULL; t->qualified_name = NULL; t->short_name = NULL; + t->impl_name = NULL; memset(&t->details, 0, sizeof(t->details)); t->typestring_offset = 0; t->ptrdesc = 0; @@ -128,6 +129,13 @@ static size_t append_namespaces(char **buf, size_t *len, size_t pos, struct name return n; }
+static size_t append_pointer_stars(char **buf, size_t *len, size_t pos, type_t *type) +{ + size_t n = 0; + for (; type && type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) n += strappend(buf, len, pos + n, "*"); + return n; +} + static size_t append_type_signature(char **buf, size_t *len, size_t pos, type_t *type);
static size_t append_var_list_signature(char **buf, size_t *len, size_t pos, var_list_t *var_list) @@ -267,9 +275,9 @@ char *format_parameterized_type_name(type_t *type, typeref_list_t *params) pos += strappend(&buf, &len, pos, "%s<", 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 += append_namespaces(&buf, &len, pos, type->namespace, "", "::", type->name, use_abi_namespace ? "ABI" : NULL); - for (type = ref->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) pos += strappend(&buf, &len, pos, "*"); + type = type_pointer_get_root_type(ref->type); + pos += strappend(&buf, &len, pos, "%s", type->qualified_name); + pos += append_pointer_stars(&buf, &len, pos, ref->type); if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ","); } pos += strappend(&buf, &len, pos, ">"); @@ -293,7 +301,7 @@ static char *format_parameterized_type_c_name(type_t *type, typeref_list_t *para pos += strappend(&buf, &len, pos, "%s%s_%d", prefix, type->name, count); 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)) {} + type = type_pointer_get_root_type(ref->type); pos += append_namespaces(&buf, &len, pos, type->namespace, "_", "__C", type->name, NULL); }
@@ -344,13 +352,45 @@ static char *format_parameterized_type_short_name(type_t *type, typeref_list_t * 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)) {} + type = type_pointer_get_root_type(ref->type); pos += strappend(&buf, &len, pos, "_%s", type->name); }
return buf; }
+static char *format_parameterized_type_impl_name(type_t *type, typeref_list_t *params, const char *prefix) +{ + size_t len = 0, pos = 0; + char *buf = NULL; + typeref_t *ref; + type_t *iface; + + pos += strappend(&buf, &len, pos, "%s%s_impl<", prefix, type->name); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + type = type_pointer_get_root_type(ref->type); + if (type->type_type == TYPE_RUNTIMECLASS) + { + pos += strappend(&buf, &len, pos, "ABI::Windows::Foundation::Internal::AggregateType<%s", type->qualified_name); + pos += append_pointer_stars(&buf, &len, pos, ref->type); + iface = type_runtimeclass_get_default_iface(type); + pos += strappend(&buf, &len, pos, ", %s", iface->qualified_name); + pos += append_pointer_stars(&buf, &len, pos, ref->type); + pos += strappend(&buf, &len, pos, ">"); + } + else + { + pos += strappend(&buf, &len, pos, "%s", type->qualified_name); + pos += append_pointer_stars(&buf, &len, pos, ref->type); + } + if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ", "); + } + pos += strappend(&buf, &len, pos, ">"); + + return buf; +} + type_t *type_new_function(var_list_t *args) { var_t *arg; @@ -1245,11 +1285,13 @@ type_t *type_parameterized_type_specialize_define(type_t *type) error_loc("pinterface/pdelegate %s previously not declared a pinterface/pdelegate at %s:%d\n", iface->name, iface->loc_info.input_name, iface->loc_info.line_number);
+ iface->impl_name = format_parameterized_type_impl_name(type, repl, ""); iface->signature = format_parameterized_type_signature(type, repl); iface->defined = TRUE; if (iface->type_type == TYPE_DELEGATE) { iface = iface->details.delegate.iface; + iface->impl_name = format_parameterized_type_impl_name(type, repl, "I"); iface->signature = format_parameterized_type_signature(type, repl); iface->defined = TRUE; } diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 0b7cd385cc2..b9833dc4e8f 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -411,6 +411,12 @@ static inline type_t *type_pointer_get_ref_type(const type_t *type) return type_pointer_get_ref(type)->type; }
+static inline type_t *type_pointer_get_root_type(type_t *type) +{ + for (; type && type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} + return type; +} + static inline type_t *type_bitfield_get_field(const type_t *type) { type = type_get_real_type(type); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index bedba40d903..7c4465418dd 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -505,6 +505,7 @@ struct _type_t { const char *signature; const char *qualified_name; const char *short_name; + const char *impl_name; unsigned int typestring_offset; unsigned int ptrdesc; /* used for complex structs */ int typelib_idx;
MinGW g++ requires initialized selectany to have extern linkage. We also defines WCHAR as char16_t, so it cannot be initialized from L"" strings.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/header.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c index b8fe3c1c445..bff51815fcd 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1890,8 +1890,12 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass) fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n"); + fprintf(header, "#ifdef __cplusplus\n"); + fprintf(header, "extern const DECLSPEC_SELECTANY wchar_t RuntimeClass_%s[] = L"%s";\n", c_name, name); + fprintf(header, "#else\n"); /* FIXME: MIDL generates extern const here but GCC warns if extern is initialized */ fprintf(header, "const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L"%s";\n", c_name, name); + fprintf(header, "#endif\n"); fprintf(header, "#else\n"); fprintf(header, "static const WCHAR RuntimeClass_%s[] = {", c_name); for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
On 22.02.2021 10:03, Rémi Bernon wrote:
fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n");
- fprintf(header, "#ifdef __cplusplus\n");
- fprintf(header, "extern const DECLSPEC_SELECTANY wchar_t RuntimeClass_%s[] = L"%s";\n", c_name, name);
- fprintf(header, "#else\n");
I think we want to stick with WCHAR, otherwise you wouldn't be able to pass it to Windows APIs. Maybe you could check defined(WINE_UNICODE_NATIVE) and use u"" form like we do for __TEXT macro in winnt.rh.
Thanks,
Jacek
Hi Rémi,
On 22.02.2021 10:02, Rémi Bernon wrote:
+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 */
Not a big deal, but maybe the helper should take care of that instead? For example NULL suffix could case the separator not to be appended.
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;
Do you expect it to use useful outside void write_widl_using_macros()? It looks like something specific to that, so maybe we could just generate it there, when needed.
Thanks,
Jacek
On 2/25/21 2:34 PM, Jacek Caban wrote:
Hi Rémi,
On 22.02.2021 10:02, Rémi Bernon wrote:
+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 */
Not a big deal, but maybe the helper should take care of that instead? For example NULL suffix could case the separator not to be appended.
Sure.
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;
Do you expect it to use useful outside void write_widl_using_macros()? It looks like something specific to that, so maybe we could just generate it there, when needed.
I'm not sure if we can do that easily there, as we don't have anymore the knowledge of which type was parameterized and which not. I'll probably keep it like this.
Thanks,
Jacek
Rémi Bernon rbernon@codeweavers.com