From aff6b930a1ad3650a3703dee5d88b1943fb7d99a Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Mon, 11 Nov 2024 17:42:53 +0800 Subject: [PATCH] gwin32: Add g_win32_clear_com() This is quite similar in concept to what g_clear_object() does, except that is meant to deal with Windows COM objects. Note that there is a separate C++ version available for this as there are COM interfaces that are available in C++ only, such as DirectWrite that is shipped with the Windows SDK (albeit a C interface is provided with the mingw-w64 toolchain. This will call `->Release()` on the non-NULL COM object referenced by its pointer and sets the COM object to NULL; if the pointer refers to a NULL COM object, this is a no-op. --- glib/gwin32.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/glib/gwin32.h b/glib/gwin32.h index e38a7f90a..63460f2f1 100644 --- a/glib/gwin32.h +++ b/glib/gwin32.h @@ -43,6 +43,11 @@ G_BEGIN_DECLS #ifdef G_OS_WIN32 +/* needed include for C++ builds; including this in C mode will cause havoc of type conflicts */ +#ifdef __cplusplus +#include +#endif + /* * To get prototypes for the following POSIXish functions, you have to * include the indicated non-POSIX headers. The functions are defined @@ -135,8 +140,60 @@ gboolean g_win32_check_windows_version (const gint major, const gint spver, const GWin32OSType os_type); +/** + * g_win32_clear_com: + * @com_obj: (not optional) (nullable): Pointer to COM object pointer to release and clear + * + * Releases the referenced COM object, and clears its pointer to `NULL`. + * + * The @com_obj pointer must not be `NULL`. + * + * If @com_obj references a `NULL` COM object, this function is a no-op. + * + * This is equivalent to `g_clear_object()` for dealing with + * Windows COM objects. + * + * Since: 2.84 + */ + +#ifndef __cplusplus + +#define g_win32_clear_com(com_obj) \ +G_STMT_START {\ + IUnknown **unknown_com_obj = (IUnknown **)(com_obj); \ + \ + if (*unknown_com_obj) \ + { \ + (*unknown_com_obj)->lpVtbl->Release (*unknown_com_obj); \ + *unknown_com_obj = NULL; \ + } \ +} G_STMT_END \ +GLIB_AVAILABLE_MACRO_IN_2_84 + +#endif + G_END_DECLS +#ifdef __cplusplus +/* + * There are COM objects that only have C++-style definitions, such as DirectWrite + * from the Windows SDK (albeit a C interface is provided for the mingw-w64 toolchain), + * so we need to have a C++ version for this + */ +template +inline void +g_win32_clear_com (com_interface **com_obj) +{ + IUnknown **unknown_com_obj = reinterpret_cast(com_obj); + + if (*unknown_com_obj != NULL) + { + (*unknown_com_obj)->Release (); + *unknown_com_obj = NULL; + } +} +#endif + #endif /* G_PLATFORM_WIN32 */ #endif /* __G_WIN32_H__ */