cb_rules.py 22 KB

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