python.py 5.7 KB

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