comparison 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
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 '''
2 Things for generating Python-specific output.
3 '''
4
5 import jlib
6
7 from . import cpp
8 from . import parse
9 from . import rename
10 from . import state
11 from . import util
12
13
14 def make_outparam_helper_python(
15 tu,
16 cursor,
17 fnname,
18 fnname_wrapper,
19 generated,
20 main_name,
21 ):
22 # Write python wrapper.
23 return_void = cursor.result_type.spelling == 'void'
24 generated.swig_python.write('')
25 generated.swig_python.write(f'def {main_name}(')
26 sep = ''
27 for arg in parse.get_args( tu, cursor):
28 if arg.out_param:
29 continue
30 generated.swig_python.write(f'{sep}{arg.name_python}')
31 sep = ', '
32 generated.swig_python.write('):\n')
33 generated.swig_python.write(f' """\n')
34 generated.swig_python.write(f' Wrapper for out-params of {cursor.spelling}().\n')
35 sep = ''
36 generated.swig_python.write(f' Returns: ')
37 sep = ''
38 if not return_void:
39 generated.swig_python.write( f'{cursor.result_type.spelling}')
40 sep = ', '
41 for arg in parse.get_args( tu, cursor):
42 if arg.out_param:
43 generated.swig_python.write(f'{sep}{cpp.declaration_text(arg.cursor.type.get_pointee(), arg.name_python)}')
44 sep = ', '
45 generated.swig_python.write(f'\n')
46 generated.swig_python.write(f' """\n')
47 generated.swig_python.write(f' outparams = {main_name}_outparams()\n')
48 generated.swig_python.write(f' ret = {main_name}_outparams_fn(')
49 sep = ''
50 for arg in parse.get_args( tu, cursor):
51 if arg.out_param:
52 continue
53 generated.swig_python.write(f'{sep}{arg.name_python}')
54 sep = ', '
55 generated.swig_python.write(f'{sep}outparams)\n')
56 generated.swig_python.write(f' return ')
57 sep = ''
58 if not return_void:
59 generated.swig_python.write(f'ret')
60 sep = ', '
61 for arg in parse.get_args( tu, cursor):
62 if arg.out_param:
63 generated.swig_python.write(f'{sep}outparams.{arg.name_python}')
64 sep = ', '
65 generated.swig_python.write('\n')
66 generated.swig_python.write('\n')
67
68
69 def cppyy_add_outparams_wrapper(
70 tu,
71 fn_name,
72 fn_cursor,
73 state_,
74 generated,
75 ):
76
77 parse.find_wrappable_function_with_arg0_type_cache_populate( tu)
78
79 def get_ctype_name( arg):
80 type_name = state.get_name_canonical( arg.cursor.type.get_pointee()).spelling
81 if type_name in (
82 'char',
83 'double',
84 'float',
85 'int',
86 'long',
87 'short',
88 ):
89 return f'ctypes.c_{type_name}'
90 elif type_name == 'unsigned long': return 'ctypes.c_ulong'
91 elif type_name == 'unsigned short': return 'ctypes.c_ushort'
92 elif type_name == 'unsigned int': return 'ctypes.c_uint'
93 else:
94 return None
95 num_out_params = 0
96 arg0 = None
97 for arg in parse.get_args( tu, fn_cursor):
98 if arg0 is None:
99 arg0 = arg
100 if arg.out_param:
101 if not get_ctype_name( arg):
102 #jlib.log( 'Not creating cppyy out-param wrapper for {fn_name}() because cannot handle {arg.cursor.type.spelling=}')
103 return
104 num_out_params += 1
105 if num_out_params:
106 return_void = fn_cursor.result_type.spelling == 'void'
107 text = ''
108 text += f'# Patch mupdf.m{fn_name} to return out-params directly.\n'
109 text += f'mupdf_m{fn_name}_original = cppyy.gbl.mupdf.m{fn_name}\n'
110 text += f'def mupdf_m{fn_name}( '
111 sep = ''
112 for arg in parse.get_args( tu, fn_cursor):
113 if arg.out_param:
114 pass
115 else:
116 text += f'{sep}{arg.name_python}'
117 sep = ', '
118 text += f'):\n'
119 for arg in parse.get_args( tu, fn_cursor):
120 if arg.out_param:
121 ctype_name = get_ctype_name( arg)
122 text += f' {arg.name_python} = {ctype_name}()\n'
123 text += f' ret = mupdf_m{fn_name}_original( '
124 sep = ''
125 for arg in parse.get_args( tu, fn_cursor):
126 if arg.out_param:
127 text += f'{sep}ctypes.pointer( {arg.name_python})'
128 else:
129 text += f'{sep}{arg.name_python}'
130 sep = ', '
131 text += f')\n'
132 sep = ' '
133 text += f' return'
134 if not return_void:
135 text += ' ret'
136 sep = ', '
137 for arg in parse.get_args( tu, fn_cursor):
138 if arg.out_param:
139 text += f'{sep}{arg.name_python}.value'
140 sep = ', '
141 text += f'\n'
142 text += f'cppyy.gbl.mupdf.m{fn_name} = mupdf_m{fn_name}\n'
143
144 # Look for class method that will use mupdf.m<fn_name>.
145 #Generated
146 struct_name = parse.find_class_for_wrappable_function( fn_name)
147 if struct_name:
148 class_name = rename.class_( struct_name)
149 method_name = rename.method( struct_name, fn_name)
150 text += f'# Also patch Python version of {fn_name}() in class wrapper for {struct_name} method {class_name}::{method_name}()\n'
151 text += f'cppyy.gbl.mupdf.{class_name}.{method_name}_original = cppyy.gbl.mupdf.{class_name}.{method_name}\n'
152 text += f'cppyy.gbl.mupdf.{class_name}.{method_name} = mupdf_m{fn_name}\n'
153 else:
154 pass
155 #jlib.log( 'Not a method of a class: {fn_name=}')
156
157 text += f'\n'
158
159 generated.cppyy_extra += text
160
161 if 0:
162 jlib.log( 'parse.fnname_to_method_structname [{len(parse.fnname_to_method_structname)}]:')
163 for fn_name, struct_name in parse.fnname_to_method_structname.items():
164 jlib.log( ' {fn_name}: {struct_name}')