From 4c4b8249ad4681b45b60b11acee74a2ab03449c5 Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Fri, 28 Jun 2024 16:13:07 +0100 Subject: [PATCH] scripts/wrap/ docs/: added operator bool() to non-pod wrapper classes. Trace diagnostics for operator bool() are generated in debug builds if MUPDF_trace=1. --- docs/src/language-bindings.rst | 16 +++++++++++++++ scripts/wrap/cpp.py | 37 ++++++++++++++++++++++++++++++++-- scripts/wrap/swig.py | 2 +- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/docs/src/language-bindings.rst b/docs/src/language-bindings.rst index 937aa5871..ad8dc141e 100644 --- a/docs/src/language-bindings.rst +++ b/docs/src/language-bindings.rst @@ -121,6 +121,22 @@ instead of MuPDF C structs: * Class-aware functions are declared in `mupdf/platform/c++/include/mupdf/classes2.h`. +* + Wrapper classes for reference-counted MuPDF structs: + + * + The C++ wrapper classes will have a public `m_internal` member that is a + pointer to the MuPDF struct. + + * + If a MuPDF functions returns a null pointer to a MuPDF struct, the + class-aware C++ wrapper will return an instance of the wrapper class with a + null `m_internal` member. + + * + The C++ wrapper class wil have an `operator bool()` that returns true if + the `m_internal` member is non-null. + Usually it is more convenient to use the class-aware C++ API rather than the low-level C++ API. diff --git a/scripts/wrap/cpp.py b/scripts/wrap/cpp.py index 051f560b6..4e1c773d8 100644 --- a/scripts/wrap/cpp.py +++ b/scripts/wrap/cpp.py @@ -3306,9 +3306,13 @@ def class_custom_method( return_space = '' comment = 'Custom destructor.' is_destructor = True + elif extramethod.name_args.startswith('operator '): + name_args = extramethod.name_args + comment = 'Custom operator.' + return_space = '' else: # Constructor. - assert extramethod.name_args.startswith( '('), f'bad constructor/destructor in classname={classname}' + assert extramethod.name_args.startswith( '('), f'bad constructor/destructor in {classname=}: {extramethod.name_args=}' name_args = f'{classname}{extramethod.name_args}' return_space = '' comment = 'Custom constructor.' @@ -4509,7 +4513,7 @@ class has custom begin() and end() methods; is true if we ) # If class has '{structname}* m_internal;', provide access to m_iternal as - # an integer, for use by python etc. + # an integer, for use by python etc, and provide `operator bool()`. if not extras.pod: class_custom_method( tu, @@ -4530,6 +4534,35 @@ class has custom begin() and end() methods; is true if we out_cpp, refcheck_if, ) + class_custom_method( + tu, + register_fn_use, + struct_cursor, + classname, + classes.ExtraMethod( + '', + 'operator bool()', + f''' + {{ + {refcheck_if} + if (s_trace) + {{ + std::cerr << __FILE__ << ":" << __LINE__ << ":" + << " {classname}::operator bool() called," + << " m_internal=" << m_internal << "." + << "\\n"; + }} + #endif + return m_internal ? true : false; + }} + ''', + '/** Return true iff `m_internal` is not null. */', + ), + out_h, + out_cpp, + refcheck_if, + ) + # Class members. # out_h.write( '\n') diff --git a/scripts/wrap/swig.py b/scripts/wrap/swig.py index 2f2f3dc94..beda76f57 100644 --- a/scripts/wrap/swig.py +++ b/scripts/wrap/swig.py @@ -1579,7 +1579,7 @@ def FzDocumentWriter__init__1(self, *args): if isinstance( arg, FzOutput2): assert not out, "More than one FzOutput2 passed to FzDocumentWriter.__init__()" out = arg - if out: + if out is not None: self._out = out return FzDocumentWriter__init__0(self, *args) FzDocumentWriter.__init__ = FzDocumentWriter__init__1