cb_rules.py 24 KB

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