diff mupdf-source/scripts/wrap/python.py @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/scripts/wrap/python.py	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,164 @@
+'''
+Things for generating Python-specific output.
+'''
+
+import jlib
+
+from . import cpp
+from . import parse
+from . import rename
+from . import state
+from . import util
+
+
+def make_outparam_helper_python(
+        tu,
+        cursor,
+        fnname,
+        fnname_wrapper,
+        generated,
+        main_name,
+        ):
+    # Write python wrapper.
+    return_void = cursor.result_type.spelling == 'void'
+    generated.swig_python.write('')
+    generated.swig_python.write(f'def {main_name}(')
+    sep = ''
+    for arg in parse.get_args( tu, cursor):
+        if arg.out_param:
+            continue
+        generated.swig_python.write(f'{sep}{arg.name_python}')
+        sep = ', '
+    generated.swig_python.write('):\n')
+    generated.swig_python.write(f'    """\n')
+    generated.swig_python.write(f'    Wrapper for out-params of {cursor.spelling}().\n')
+    sep = ''
+    generated.swig_python.write(f'    Returns: ')
+    sep = ''
+    if not return_void:
+        generated.swig_python.write( f'{cursor.result_type.spelling}')
+        sep = ', '
+    for arg in parse.get_args( tu, cursor):
+        if arg.out_param:
+            generated.swig_python.write(f'{sep}{cpp.declaration_text(arg.cursor.type.get_pointee(), arg.name_python)}')
+            sep = ', '
+    generated.swig_python.write(f'\n')
+    generated.swig_python.write(f'    """\n')
+    generated.swig_python.write(f'    outparams = {main_name}_outparams()\n')
+    generated.swig_python.write(f'    ret = {main_name}_outparams_fn(')
+    sep = ''
+    for arg in parse.get_args( tu, cursor):
+        if arg.out_param:
+            continue
+        generated.swig_python.write(f'{sep}{arg.name_python}')
+        sep = ', '
+    generated.swig_python.write(f'{sep}outparams)\n')
+    generated.swig_python.write(f'    return ')
+    sep = ''
+    if not return_void:
+        generated.swig_python.write(f'ret')
+        sep = ', '
+    for arg in parse.get_args( tu, cursor):
+        if arg.out_param:
+            generated.swig_python.write(f'{sep}outparams.{arg.name_python}')
+            sep = ', '
+    generated.swig_python.write('\n')
+    generated.swig_python.write('\n')
+
+
+def cppyy_add_outparams_wrapper(
+        tu,
+        fn_name,
+        fn_cursor,
+        state_,
+        generated,
+        ):
+
+    parse.find_wrappable_function_with_arg0_type_cache_populate( tu)
+
+    def get_ctype_name( arg):
+        type_name = state.get_name_canonical( arg.cursor.type.get_pointee()).spelling
+        if type_name in (
+                'char',
+                'double',
+                'float',
+                'int',
+                'long',
+                'short',
+                ):
+            return f'ctypes.c_{type_name}'
+        elif type_name == 'unsigned long':  return 'ctypes.c_ulong'
+        elif type_name == 'unsigned short': return 'ctypes.c_ushort'
+        elif type_name == 'unsigned int':   return 'ctypes.c_uint'
+        else:
+            return None
+    num_out_params = 0
+    arg0 = None
+    for arg in parse.get_args( tu, fn_cursor):
+        if arg0 is None:
+            arg0 = arg
+        if arg.out_param:
+            if not get_ctype_name( arg):
+                #jlib.log( 'Not creating cppyy out-param wrapper for {fn_name}() because cannot handle {arg.cursor.type.spelling=}')
+                return
+            num_out_params += 1
+    if num_out_params:
+        return_void = fn_cursor.result_type.spelling == 'void'
+        text = ''
+        text += f'# Patch mupdf.m{fn_name} to return out-params directly.\n'
+        text += f'mupdf_m{fn_name}_original = cppyy.gbl.mupdf.m{fn_name}\n'
+        text += f'def mupdf_m{fn_name}( '
+        sep = ''
+        for arg in parse.get_args( tu, fn_cursor):
+            if arg.out_param:
+                pass
+            else:
+                text += f'{sep}{arg.name_python}'
+                sep = ', '
+        text += f'):\n'
+        for arg in parse.get_args( tu, fn_cursor):
+            if arg.out_param:
+                ctype_name = get_ctype_name( arg)
+                text += f'    {arg.name_python} = {ctype_name}()\n'
+        text += f'    ret = mupdf_m{fn_name}_original( '
+        sep = ''
+        for arg in parse.get_args( tu, fn_cursor):
+            if arg.out_param:
+                text += f'{sep}ctypes.pointer( {arg.name_python})'
+            else:
+                text += f'{sep}{arg.name_python}'
+            sep = ', '
+        text += f')\n'
+        sep = ' '
+        text += f'    return'
+        if not return_void:
+            text += ' ret'
+            sep = ', '
+        for arg in parse.get_args( tu, fn_cursor):
+            if arg.out_param:
+                text += f'{sep}{arg.name_python}.value'
+                sep = ', '
+        text += f'\n'
+        text += f'cppyy.gbl.mupdf.m{fn_name} = mupdf_m{fn_name}\n'
+
+        # Look for class method that will use mupdf.m<fn_name>.
+        #Generated
+        struct_name = parse.find_class_for_wrappable_function( fn_name)
+        if struct_name:
+            class_name = rename.class_( struct_name)
+            method_name = rename.method( struct_name, fn_name)
+            text += f'# Also patch Python version of {fn_name}() in class wrapper for {struct_name} method {class_name}::{method_name}()\n'
+            text += f'cppyy.gbl.mupdf.{class_name}.{method_name}_original = cppyy.gbl.mupdf.{class_name}.{method_name}\n'
+            text += f'cppyy.gbl.mupdf.{class_name}.{method_name} = mupdf_m{fn_name}\n'
+        else:
+            pass
+            #jlib.log( 'Not a method of a class: {fn_name=}')
+
+        text += f'\n'
+
+        generated.cppyy_extra += text
+
+    if 0:
+        jlib.log( 'parse.fnname_to_method_structname [{len(parse.fnname_to_method_structname)}]:')
+        for fn_name, struct_name in parse.fnname_to_method_structname.items():
+            jlib.log( '    {fn_name}: {struct_name}')