cb_rules.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. #!/usr/bin/env python3
  2. """
  3. Build call-back mechanism for f2py2e.
  4. Copyright 2000 Pearu Peterson all rights reserved,
  5. Pearu Peterson <pearu@ioc.ee>
  6. Permission to use, modify, and distribute this software is given under the
  7. terms of the NumPy License.
  8. NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
  9. $Date: 2005/07/20 11:27:58 $
  10. Pearu Peterson
  11. """
  12. from . import __version__
  13. from .auxfuncs import (
  14. applyrules, debugcapi, dictappend, errmess, getargs, hasnote, isarray,
  15. iscomplex, iscomplexarray, iscomplexfunction, isfunction, isintent_c,
  16. isintent_hide, isintent_in, isintent_inout, isintent_nothide,
  17. isintent_out, isoptional, isrequired, isscalar, isstring,
  18. isstringfunction, issubroutine, l_and, l_not, l_or, outmess, replace,
  19. stripcomma, throw_error
  20. )
  21. from . import cfuncs
  22. f2py_version = __version__.version
  23. ################## Rules for callback function ##############
  24. cb_routine_rules = {
  25. 'cbtypedefs': 'typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);',
  26. 'body': """
  27. #begintitle#
  28. PyObject *#name#_capi = NULL;/*was Py_None*/
  29. PyTupleObject *#name#_args_capi = NULL;
  30. int #name#_nofargs = 0;
  31. jmp_buf #name#_jmpbuf;
  32. /*typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);*/
  33. #static# #rctype# #callbackname# (#optargs##args##strarglens##noargs#) {
  34. \tPyTupleObject *capi_arglist = #name#_args_capi;
  35. \tPyObject *capi_return = NULL;
  36. \tPyObject *capi_tmp = NULL;
  37. \tPyObject *capi_arglist_list = NULL;
  38. \tint capi_j,capi_i = 0;
  39. \tint capi_longjmp_ok = 1;
  40. #decl#
  41. #ifdef F2PY_REPORT_ATEXIT
  42. f2py_cb_start_clock();
  43. #endif
  44. \tCFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\");
  45. \tCFUNCSMESSPY(\"cb:#name#_capi=\",#name#_capi);
  46. \tif (#name#_capi==NULL) {
  47. \t\tcapi_longjmp_ok = 0;
  48. \t\t#name#_capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\");
  49. \t}
  50. \tif (#name#_capi==NULL) {
  51. \t\tPyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\");
  52. \t\tgoto capi_fail;
  53. \t}
  54. \tif (F2PyCapsule_Check(#name#_capi)) {
  55. \t#name#_typedef #name#_cptr;
  56. \t#name#_cptr = F2PyCapsule_AsVoidPtr(#name#_capi);
  57. \t#returncptr#(*#name#_cptr)(#optargs_nm##args_nm##strarglens_nm#);
  58. \t#return#
  59. \t}
  60. \tif (capi_arglist==NULL) {
  61. \t\tcapi_longjmp_ok = 0;
  62. \t\tcapi_tmp = PyObject_GetAttrString(#modulename#_module,\"#argname#_extra_args\");
  63. \t\tif (capi_tmp) {
  64. \t\t\tcapi_arglist = (PyTupleObject *)PySequence_Tuple(capi_tmp);
  65. \t\t\tif (capi_arglist==NULL) {
  66. \t\t\t\tPyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#argname#_extra_args to tuple.\\n\");
  67. \t\t\t\tgoto capi_fail;
  68. \t\t\t}
  69. \t\t} else {
  70. \t\t\tPyErr_Clear();
  71. \t\t\tcapi_arglist = (PyTupleObject *)Py_BuildValue(\"()\");
  72. \t\t}
  73. \t}
  74. \tif (capi_arglist == NULL) {
  75. \t\tPyErr_SetString(#modulename#_error,\"Callback #argname# argument list is not set.\\n\");
  76. \t\tgoto capi_fail;
  77. \t}
  78. #setdims#
  79. #ifdef PYPY_VERSION
  80. #define CAPI_ARGLIST_SETITEM(idx, value) PyList_SetItem((PyObject *)capi_arglist_list, idx, value)
  81. \tcapi_arglist_list = PySequence_List(capi_arglist);
  82. \tif (capi_arglist_list == NULL) goto capi_fail;
  83. #else
  84. #define CAPI_ARGLIST_SETITEM(idx, value) PyTuple_SetItem((PyObject *)capi_arglist, idx, value)
  85. #endif
  86. #pyobjfrom#
  87. #undef CAPI_ARGLIST_SETITEM
  88. #ifdef PYPY_VERSION
  89. \tCFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist_list);
  90. #else
  91. \tCFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist);
  92. #endif
  93. \tCFUNCSMESS(\"cb:Call-back calling Python function #argname#.\\n\");
  94. #ifdef F2PY_REPORT_ATEXIT
  95. f2py_cb_start_call_clock();
  96. #endif
  97. #ifdef PYPY_VERSION
  98. \tcapi_return = PyObject_CallObject(#name#_capi,(PyObject *)capi_arglist_list);
  99. \tPy_DECREF(capi_arglist_list);
  100. \tcapi_arglist_list = NULL;
  101. #else
  102. \tcapi_return = PyObject_CallObject(#name#_capi,(PyObject *)capi_arglist);
  103. #endif
  104. #ifdef F2PY_REPORT_ATEXIT
  105. f2py_cb_stop_call_clock();
  106. #endif
  107. \tCFUNCSMESSPY(\"cb:capi_return=\",capi_return);
  108. \tif (capi_return == NULL) {
  109. \t\tfprintf(stderr,\"capi_return is NULL\\n\");
  110. \t\tgoto capi_fail;
  111. \t}
  112. \tif (capi_return == Py_None) {
  113. \t\tPy_DECREF(capi_return);
  114. \t\tcapi_return = Py_BuildValue(\"()\");
  115. \t}
  116. \telse if (!PyTuple_Check(capi_return)) {
  117. \t\tcapi_return = Py_BuildValue(\"(N)\",capi_return);
  118. \t}
  119. \tcapi_j = PyTuple_Size(capi_return);
  120. \tcapi_i = 0;
  121. #frompyobj#
  122. \tCFUNCSMESS(\"cb:#name#:successful\\n\");
  123. \tPy_DECREF(capi_return);
  124. #ifdef F2PY_REPORT_ATEXIT
  125. f2py_cb_stop_clock();
  126. #endif
  127. \tgoto capi_return_pt;
  128. capi_fail:
  129. \tfprintf(stderr,\"Call-back #name# failed.\\n\");
  130. \tPy_XDECREF(capi_return);
  131. \tPy_XDECREF(capi_arglist_list);
  132. \tif (capi_longjmp_ok)
  133. \t\tlongjmp(#name#_jmpbuf,-1);
  134. capi_return_pt:
  135. \t;
  136. #return#
  137. }
  138. #endtitle#
  139. """,
  140. 'need': ['setjmp.h', 'CFUNCSMESS'],
  141. 'maxnofargs': '#maxnofargs#',
  142. 'nofoptargs': '#nofoptargs#',
  143. 'docstr': """\
  144. \tdef #argname#(#docsignature#): return #docreturn#\\n\\
  145. #docstrsigns#""",
  146. 'latexdocstr': """
  147. {{}\\verb@def #argname#(#latexdocsignature#): return #docreturn#@{}}
  148. #routnote#
  149. #latexdocstrsigns#""",
  150. 'docstrshort': 'def #argname#(#docsignature#): return #docreturn#'
  151. }
  152. cb_rout_rules = [
  153. { # Init
  154. 'separatorsfor': {'decl': '\n',
  155. 'args': ',', 'optargs': '', 'pyobjfrom': '\n', 'freemem': '\n',
  156. 'args_td': ',', 'optargs_td': '',
  157. 'args_nm': ',', 'optargs_nm': '',
  158. 'frompyobj': '\n', 'setdims': '\n',
  159. 'docstrsigns': '\\n"\n"',
  160. 'latexdocstrsigns': '\n',
  161. 'latexdocstrreq': '\n', 'latexdocstropt': '\n',
  162. 'latexdocstrout': '\n', 'latexdocstrcbs': '\n',
  163. },
  164. 'decl': '/*decl*/', 'pyobjfrom': '/*pyobjfrom*/', 'frompyobj': '/*frompyobj*/',
  165. 'args': [], 'optargs': '', 'return': '', 'strarglens': '', 'freemem': '/*freemem*/',
  166. 'args_td': [], 'optargs_td': '', 'strarglens_td': '',
  167. 'args_nm': [], 'optargs_nm': '', 'strarglens_nm': '',
  168. 'noargs': '',
  169. 'setdims': '/*setdims*/',
  170. 'docstrsigns': '', 'latexdocstrsigns': '',
  171. 'docstrreq': '\tRequired arguments:',
  172. 'docstropt': '\tOptional arguments:',
  173. 'docstrout': '\tReturn objects:',
  174. 'docstrcbs': '\tCall-back functions:',
  175. 'docreturn': '', 'docsign': '', 'docsignopt': '',
  176. 'latexdocstrreq': '\\noindent Required arguments:',
  177. 'latexdocstropt': '\\noindent Optional arguments:',
  178. 'latexdocstrout': '\\noindent Return objects:',
  179. 'latexdocstrcbs': '\\noindent Call-back functions:',
  180. 'routnote': {hasnote: '--- #note#', l_not(hasnote): ''},
  181. }, { # Function
  182. 'decl': '\t#ctype# return_value;',
  183. 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting return_value->");'},
  184. '\tif (capi_j>capi_i)\n\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n");',
  185. {debugcapi:
  186. '\tfprintf(stderr,"#showvalueformat#.\\n",return_value);'}
  187. ],
  188. 'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'}, 'GETSCALARFROMPYTUPLE'],
  189. 'return': '\treturn return_value;',
  190. '_check': l_and(isfunction, l_not(isstringfunction), l_not(iscomplexfunction))
  191. },
  192. { # String function
  193. 'pyobjfrom': {debugcapi: '\tfprintf(stderr,"debug-capi:cb:#name#:%d:\\n",return_value_len);'},
  194. 'args': '#ctype# return_value,int return_value_len',
  195. 'args_nm': 'return_value,&return_value_len',
  196. 'args_td': '#ctype# ,int',
  197. 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting return_value->\\"");'},
  198. """\tif (capi_j>capi_i)
  199. \t\tGETSTRFROMPYTUPLE(capi_return,capi_i++,return_value,return_value_len);""",
  200. {debugcapi:
  201. '\tfprintf(stderr,"#showvalueformat#\\".\\n",return_value);'}
  202. ],
  203. 'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
  204. 'string.h', 'GETSTRFROMPYTUPLE'],
  205. 'return': 'return;',
  206. '_check': isstringfunction
  207. },
  208. { # Complex function
  209. 'optargs': """
  210. #ifndef F2PY_CB_RETURNCOMPLEX
  211. #ctype# *return_value
  212. #endif
  213. """,
  214. 'optargs_nm': """
  215. #ifndef F2PY_CB_RETURNCOMPLEX
  216. return_value
  217. #endif
  218. """,
  219. 'optargs_td': """
  220. #ifndef F2PY_CB_RETURNCOMPLEX
  221. #ctype# *
  222. #endif
  223. """,
  224. 'decl': """
  225. #ifdef F2PY_CB_RETURNCOMPLEX
  226. \t#ctype# return_value;
  227. #endif
  228. """,
  229. 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting return_value->");'},
  230. """\
  231. \tif (capi_j>capi_i)
  232. #ifdef F2PY_CB_RETURNCOMPLEX
  233. \t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,\"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n\");
  234. #else
  235. \t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,return_value,#ctype#,\"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n\");
  236. #endif
  237. """,
  238. {debugcapi: """
  239. #ifdef F2PY_CB_RETURNCOMPLEX
  240. \tfprintf(stderr,\"#showvalueformat#.\\n\",(return_value).r,(return_value).i);
  241. #else
  242. \tfprintf(stderr,\"#showvalueformat#.\\n\",(*return_value).r,(*return_value).i);
  243. #endif
  244. """}
  245. ],
  246. 'return': """
  247. #ifdef F2PY_CB_RETURNCOMPLEX
  248. \treturn return_value;
  249. #else
  250. \treturn;
  251. #endif
  252. """,
  253. 'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
  254. 'string.h', 'GETSCALARFROMPYTUPLE', '#ctype#'],
  255. '_check': iscomplexfunction
  256. },
  257. {'docstrout': '\t\t#pydocsignout#',
  258. 'latexdocstrout': ['\\item[]{{}\\verb@#pydocsignout#@{}}',
  259. {hasnote: '--- #note#'}],
  260. 'docreturn': '#rname#,',
  261. '_check': isfunction},
  262. {'_check': issubroutine, 'return': 'return;'}
  263. ]
  264. cb_arg_rules = [
  265. { # Doc
  266. 'docstropt': {l_and(isoptional, isintent_nothide): '\t\t#pydocsign#'},
  267. 'docstrreq': {l_and(isrequired, isintent_nothide): '\t\t#pydocsign#'},
  268. 'docstrout': {isintent_out: '\t\t#pydocsignout#'},
  269. 'latexdocstropt': {l_and(isoptional, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
  270. {hasnote: '--- #note#'}]},
  271. 'latexdocstrreq': {l_and(isrequired, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
  272. {hasnote: '--- #note#'}]},
  273. 'latexdocstrout': {isintent_out: ['\\item[]{{}\\verb@#pydocsignout#@{}}',
  274. {l_and(hasnote, isintent_hide): '--- #note#',
  275. l_and(hasnote, isintent_nothide): '--- See above.'}]},
  276. 'docsign': {l_and(isrequired, isintent_nothide): '#varname#,'},
  277. 'docsignopt': {l_and(isoptional, isintent_nothide): '#varname#,'},
  278. 'depend': ''
  279. },
  280. {
  281. 'args': {
  282. l_and(isscalar, isintent_c): '#ctype# #varname_i#',
  283. l_and(isscalar, l_not(isintent_c)): '#ctype# *#varname_i#_cb_capi',
  284. isarray: '#ctype# *#varname_i#',
  285. isstring: '#ctype# #varname_i#'
  286. },
  287. 'args_nm': {
  288. l_and(isscalar, isintent_c): '#varname_i#',
  289. l_and(isscalar, l_not(isintent_c)): '#varname_i#_cb_capi',
  290. isarray: '#varname_i#',
  291. isstring: '#varname_i#'
  292. },
  293. 'args_td': {
  294. l_and(isscalar, isintent_c): '#ctype#',
  295. l_and(isscalar, l_not(isintent_c)): '#ctype# *',
  296. isarray: '#ctype# *',
  297. isstring: '#ctype#'
  298. },
  299. # untested with multiple args
  300. 'strarglens': {isstring: ',int #varname_i#_cb_len'},
  301. 'strarglens_td': {isstring: ',int'}, # untested with multiple args
  302. # untested with multiple args
  303. 'strarglens_nm': {isstring: ',#varname_i#_cb_len'},
  304. },
  305. { # Scalars
  306. 'decl': {l_not(isintent_c): '\t#ctype# #varname_i#=(*#varname_i#_cb_capi);'},
  307. 'error': {l_and(isintent_c, isintent_out,
  308. throw_error('intent(c,out) is forbidden for callback scalar arguments')):
  309. ''},
  310. 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting #varname#->");'},
  311. {isintent_out:
  312. '\tif (capi_j>capi_i)\n\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,#varname_i#_cb_capi,#ctype#,"#ctype#_from_pyobj failed in converting argument #varname# of call-back function #name# to C #ctype#\\n");'},
  313. {l_and(debugcapi, l_and(l_not(iscomplex), isintent_c)):
  314. '\tfprintf(stderr,"#showvalueformat#.\\n",#varname_i#);'},
  315. {l_and(debugcapi, l_and(l_not(iscomplex), l_not( isintent_c))):
  316. '\tfprintf(stderr,"#showvalueformat#.\\n",*#varname_i#_cb_capi);'},
  317. {l_and(debugcapi, l_and(iscomplex, isintent_c)):
  318. '\tfprintf(stderr,"#showvalueformat#.\\n",(#varname_i#).r,(#varname_i#).i);'},
  319. {l_and(debugcapi, l_and(iscomplex, l_not( isintent_c))):
  320. '\tfprintf(stderr,"#showvalueformat#.\\n",(*#varname_i#_cb_capi).r,(*#varname_i#_cb_capi).i);'},
  321. ],
  322. 'need': [{isintent_out: ['#ctype#_from_pyobj', 'GETSCALARFROMPYTUPLE']},
  323. {debugcapi: 'CFUNCSMESS'}],
  324. '_check': isscalar
  325. }, {
  326. 'pyobjfrom': [{isintent_in: """\
  327. \tif (#name#_nofargs>capi_i)
  328. \t\tif (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1(#varname_i#)))
  329. \t\t\tgoto capi_fail;"""},
  330. {isintent_inout: """\
  331. \tif (#name#_nofargs>capi_i)
  332. \t\tif (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#_cb_capi)))
  333. \t\t\tgoto capi_fail;"""}],
  334. 'need': [{isintent_in: 'pyobj_from_#ctype#1'},
  335. {isintent_inout: 'pyarr_from_p_#ctype#1'},
  336. {iscomplex: '#ctype#'}],
  337. '_check': l_and(isscalar, isintent_nothide),
  338. '_optional': ''
  339. }, { # String
  340. 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting #varname#->\\"");'},
  341. """\tif (capi_j>capi_i)
  342. \t\tGETSTRFROMPYTUPLE(capi_return,capi_i++,#varname_i#,#varname_i#_cb_len);""",
  343. {debugcapi:
  344. '\tfprintf(stderr,"#showvalueformat#\\":%d:.\\n",#varname_i#,#varname_i#_cb_len);'},
  345. ],
  346. 'need': ['#ctype#', 'GETSTRFROMPYTUPLE',
  347. {debugcapi: 'CFUNCSMESS'}, 'string.h'],
  348. '_check': l_and(isstring, isintent_out)
  349. }, {
  350. 'pyobjfrom': [{debugcapi: '\tfprintf(stderr,"debug-capi:cb:#varname#=\\"#showvalueformat#\\":%d:\\n",#varname_i#,#varname_i#_cb_len);'},
  351. {isintent_in: """\
  352. \tif (#name#_nofargs>capi_i)
  353. \t\tif (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1size(#varname_i#,#varname_i#_cb_len)))
  354. \t\t\tgoto capi_fail;"""},
  355. {isintent_inout: """\
  356. \tif (#name#_nofargs>capi_i) {
  357. \t\tint #varname_i#_cb_dims[] = {#varname_i#_cb_len};
  358. \t\tif (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#,#varname_i#_cb_dims)))
  359. \t\t\tgoto capi_fail;
  360. \t}"""}],
  361. 'need': [{isintent_in: 'pyobj_from_#ctype#1size'},
  362. {isintent_inout: 'pyarr_from_p_#ctype#1'}],
  363. '_check': l_and(isstring, isintent_nothide),
  364. '_optional': ''
  365. },
  366. # Array ...
  367. {
  368. 'decl': '\tnpy_intp #varname_i#_Dims[#rank#] = {#rank*[-1]#};',
  369. 'setdims': '\t#cbsetdims#;',
  370. '_check': isarray,
  371. '_depend': ''
  372. },
  373. {
  374. 'pyobjfrom': [{debugcapi: '\tfprintf(stderr,"debug-capi:cb:#varname#\\n");'},
  375. {isintent_c: """\
  376. \tif (#name#_nofargs>capi_i) {
  377. \t\tint itemsize_ = #atype# == NPY_STRING ? 1 : 0;
  378. \t\t/*XXX: Hmm, what will destroy this array??? */
  379. \t\tPyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,itemsize_,NPY_ARRAY_CARRAY,NULL);
  380. """,
  381. l_not(isintent_c): """\
  382. \tif (#name#_nofargs>capi_i) {
  383. \t\tint itemsize_ = #atype# == NPY_STRING ? 1 : 0;
  384. \t\t/*XXX: Hmm, what will destroy this array??? */
  385. \t\tPyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,itemsize_,NPY_ARRAY_FARRAY,NULL);
  386. """,
  387. },
  388. """
  389. \t\tif (tmp_arr==NULL)
  390. \t\t\tgoto capi_fail;
  391. \t\tif (CAPI_ARGLIST_SETITEM(capi_i++,(PyObject *)tmp_arr))
  392. \t\t\tgoto capi_fail;
  393. }"""],
  394. '_check': l_and(isarray, isintent_nothide, l_or(isintent_in, isintent_inout)),
  395. '_optional': '',
  396. }, {
  397. 'frompyobj': [{debugcapi: '\tCFUNCSMESS("cb:Getting #varname#->");'},
  398. """\tif (capi_j>capi_i) {
  399. \t\tPyArrayObject *rv_cb_arr = NULL;
  400. \t\tif ((capi_tmp = PyTuple_GetItem(capi_return,capi_i++))==NULL) goto capi_fail;
  401. \t\trv_cb_arr = array_from_pyobj(#atype#,#varname_i#_Dims,#rank#,F2PY_INTENT_IN""",
  402. {isintent_c: '|F2PY_INTENT_C'},
  403. """,capi_tmp);
  404. \t\tif (rv_cb_arr == NULL) {
  405. \t\t\tfprintf(stderr,\"rv_cb_arr is NULL\\n\");
  406. \t\t\tgoto capi_fail;
  407. \t\t}
  408. \t\tMEMCOPY(#varname_i#,PyArray_DATA(rv_cb_arr),PyArray_NBYTES(rv_cb_arr));
  409. \t\tif (capi_tmp != (PyObject *)rv_cb_arr) {
  410. \t\t\tPy_DECREF(rv_cb_arr);
  411. \t\t}
  412. \t}""",
  413. {debugcapi: '\tfprintf(stderr,"<-.\\n");'},
  414. ],
  415. 'need': ['MEMCOPY', {iscomplexarray: '#ctype#'}],
  416. '_check': l_and(isarray, isintent_out)
  417. }, {
  418. 'docreturn': '#varname#,',
  419. '_check': isintent_out
  420. }
  421. ]
  422. ################## Build call-back module #############
  423. cb_map = {}
  424. def buildcallbacks(m):
  425. cb_map[m['name']] = []
  426. for bi in m['body']:
  427. if bi['block'] == 'interface':
  428. for b in bi['body']:
  429. if b:
  430. buildcallback(b, m['name'])
  431. else:
  432. errmess('warning: empty body for %s\n' % (m['name']))
  433. def buildcallback(rout, um):
  434. from . import capi_maps
  435. outmess('\tConstructing call-back function "cb_%s_in_%s"\n' %
  436. (rout['name'], um))
  437. args, depargs = getargs(rout)
  438. capi_maps.depargs = depargs
  439. var = rout['vars']
  440. vrd = capi_maps.cb_routsign2map(rout, um)
  441. rd = dictappend({}, vrd)
  442. cb_map[um].append([rout['name'], rd['name']])
  443. for r in cb_rout_rules:
  444. if ('_check' in r and r['_check'](rout)) or ('_check' not in r):
  445. ar = applyrules(r, vrd, rout)
  446. rd = dictappend(rd, ar)
  447. savevrd = {}
  448. for i, a in enumerate(args):
  449. vrd = capi_maps.cb_sign2map(a, var[a], index=i)
  450. savevrd[a] = vrd
  451. for r in cb_arg_rules:
  452. if '_depend' in r:
  453. continue
  454. if '_optional' in r and isoptional(var[a]):
  455. continue
  456. if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
  457. ar = applyrules(r, vrd, var[a])
  458. rd = dictappend(rd, ar)
  459. if '_break' in r:
  460. break
  461. for a in args:
  462. vrd = savevrd[a]
  463. for r in cb_arg_rules:
  464. if '_depend' in r:
  465. continue
  466. if ('_optional' not in r) or ('_optional' in r and isrequired(var[a])):
  467. continue
  468. if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
  469. ar = applyrules(r, vrd, var[a])
  470. rd = dictappend(rd, ar)
  471. if '_break' in r:
  472. break
  473. for a in depargs:
  474. vrd = savevrd[a]
  475. for r in cb_arg_rules:
  476. if '_depend' not in r:
  477. continue
  478. if '_optional' in r:
  479. continue
  480. if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
  481. ar = applyrules(r, vrd, var[a])
  482. rd = dictappend(rd, ar)
  483. if '_break' in r:
  484. break
  485. if 'args' in rd and 'optargs' in rd:
  486. if isinstance(rd['optargs'], list):
  487. rd['optargs'] = rd['optargs'] + ["""
  488. #ifndef F2PY_CB_RETURNCOMPLEX
  489. ,
  490. #endif
  491. """]
  492. rd['optargs_nm'] = rd['optargs_nm'] + ["""
  493. #ifndef F2PY_CB_RETURNCOMPLEX
  494. ,
  495. #endif
  496. """]
  497. rd['optargs_td'] = rd['optargs_td'] + ["""
  498. #ifndef F2PY_CB_RETURNCOMPLEX
  499. ,
  500. #endif
  501. """]
  502. if isinstance(rd['docreturn'], list):
  503. rd['docreturn'] = stripcomma(
  504. replace('#docreturn#', {'docreturn': rd['docreturn']}))
  505. optargs = stripcomma(replace('#docsignopt#',
  506. {'docsignopt': rd['docsignopt']}
  507. ))
  508. if optargs == '':
  509. rd['docsignature'] = stripcomma(
  510. replace('#docsign#', {'docsign': rd['docsign']}))
  511. else:
  512. rd['docsignature'] = replace('#docsign#[#docsignopt#]',
  513. {'docsign': rd['docsign'],
  514. 'docsignopt': optargs,
  515. })
  516. rd['latexdocsignature'] = rd['docsignature'].replace('_', '\\_')
  517. rd['latexdocsignature'] = rd['latexdocsignature'].replace(',', ', ')
  518. rd['docstrsigns'] = []
  519. rd['latexdocstrsigns'] = []
  520. for k in ['docstrreq', 'docstropt', 'docstrout', 'docstrcbs']:
  521. if k in rd and isinstance(rd[k], list):
  522. rd['docstrsigns'] = rd['docstrsigns'] + rd[k]
  523. k = 'latex' + k
  524. if k in rd and isinstance(rd[k], list):
  525. rd['latexdocstrsigns'] = rd['latexdocstrsigns'] + rd[k][0:1] +\
  526. ['\\begin{description}'] + rd[k][1:] +\
  527. ['\\end{description}']
  528. if 'args' not in rd:
  529. rd['args'] = ''
  530. rd['args_td'] = ''
  531. rd['args_nm'] = ''
  532. if not (rd.get('args') or rd.get('optargs') or rd.get('strarglens')):
  533. rd['noargs'] = 'void'
  534. ar = applyrules(cb_routine_rules, rd)
  535. cfuncs.callbacks[rd['name']] = ar['body']
  536. if isinstance(ar['need'], str):
  537. ar['need'] = [ar['need']]
  538. if 'need' in rd:
  539. for t in cfuncs.typedefs.keys():
  540. if t in rd['need']:
  541. ar['need'].append(t)
  542. cfuncs.typedefs_generated[rd['name'] + '_typedef'] = ar['cbtypedefs']
  543. ar['need'].append(rd['name'] + '_typedef')
  544. cfuncs.needs[rd['name']] = ar['need']
  545. capi_maps.lcb2_map[rd['name']] = {'maxnofargs': ar['maxnofargs'],
  546. 'nofoptargs': ar['nofoptargs'],
  547. 'docstr': ar['docstr'],
  548. 'latexdocstr': ar['latexdocstr'],
  549. 'argname': rd['argname']
  550. }
  551. outmess('\t %s\n' % (ar['docstrshort']))
  552. return
  553. ################## Build call-back function #############