cb_rules.py 24 KB

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