Chris@87: #!/usr/bin/env python Chris@87: """ Chris@87: Chris@87: Build call-back mechanism for f2py2e. Chris@87: Chris@87: Copyright 2000 Pearu Peterson all rights reserved, Chris@87: Pearu Peterson Chris@87: Permission to use, modify, and distribute this software is given under the Chris@87: terms of the NumPy License. Chris@87: Chris@87: NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. Chris@87: $Date: 2005/07/20 11:27:58 $ Chris@87: Pearu Peterson Chris@87: Chris@87: """ Chris@87: from __future__ import division, absolute_import, print_function Chris@87: Chris@87: import pprint Chris@87: import sys Chris@87: Chris@87: from . import __version__ Chris@87: from .auxfuncs import * Chris@87: from . import cfuncs Chris@87: Chris@87: f2py_version = __version__.version Chris@87: Chris@87: errmess=sys.stderr.write Chris@87: outmess=sys.stdout.write Chris@87: show=pprint.pprint Chris@87: Chris@87: Chris@87: ################## Rules for callback function ############## Chris@87: Chris@87: cb_routine_rules={ Chris@87: 'cbtypedefs':'typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);', Chris@87: 'body':""" Chris@87: #begintitle# Chris@87: PyObject *#name#_capi = NULL;/*was Py_None*/ Chris@87: PyTupleObject *#name#_args_capi = NULL; Chris@87: int #name#_nofargs = 0; Chris@87: jmp_buf #name#_jmpbuf; Chris@87: /*typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);*/ Chris@87: #static# #rctype# #callbackname# (#optargs##args##strarglens##noargs#) { Chris@87: \tPyTupleObject *capi_arglist = #name#_args_capi; Chris@87: \tPyObject *capi_return = NULL; Chris@87: \tPyObject *capi_tmp = NULL; Chris@87: \tint capi_j,capi_i = 0; Chris@87: \tint capi_longjmp_ok = 1; Chris@87: #decl# Chris@87: #ifdef F2PY_REPORT_ATEXIT Chris@87: f2py_cb_start_clock(); Chris@87: #endif Chris@87: \tCFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\"); Chris@87: \tCFUNCSMESSPY(\"cb:#name#_capi=\",#name#_capi); Chris@87: \tif (#name#_capi==NULL) { Chris@87: \t\tcapi_longjmp_ok = 0; Chris@87: \t\t#name#_capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\"); Chris@87: \t} Chris@87: \tif (#name#_capi==NULL) { Chris@87: \t\tPyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\"); Chris@87: \t\tgoto capi_fail; Chris@87: \t} Chris@87: \tif (F2PyCapsule_Check(#name#_capi)) { Chris@87: \t#name#_typedef #name#_cptr; Chris@87: \t#name#_cptr = F2PyCapsule_AsVoidPtr(#name#_capi); Chris@87: \t#returncptr#(*#name#_cptr)(#optargs_nm##args_nm##strarglens_nm#); Chris@87: \t#return# Chris@87: \t} Chris@87: \tif (capi_arglist==NULL) { Chris@87: \t\tcapi_longjmp_ok = 0; Chris@87: \t\tcapi_tmp = PyObject_GetAttrString(#modulename#_module,\"#argname#_extra_args\"); Chris@87: \t\tif (capi_tmp) { Chris@87: \t\t\tcapi_arglist = (PyTupleObject *)PySequence_Tuple(capi_tmp); Chris@87: \t\t\tif (capi_arglist==NULL) { Chris@87: \t\t\t\tPyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#argname#_extra_args to tuple.\\n\"); Chris@87: \t\t\t\tgoto capi_fail; Chris@87: \t\t\t} Chris@87: \t\t} else { Chris@87: \t\t\tPyErr_Clear(); Chris@87: \t\t\tcapi_arglist = (PyTupleObject *)Py_BuildValue(\"()\"); Chris@87: \t\t} Chris@87: \t} Chris@87: \tif (capi_arglist == NULL) { Chris@87: \t\tPyErr_SetString(#modulename#_error,\"Callback #argname# argument list is not set.\\n\"); Chris@87: \t\tgoto capi_fail; Chris@87: \t} Chris@87: #setdims# Chris@87: #pyobjfrom# Chris@87: \tCFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist); Chris@87: \tCFUNCSMESS(\"cb:Call-back calling Python function #argname#.\\n\"); Chris@87: #ifdef F2PY_REPORT_ATEXIT Chris@87: f2py_cb_start_call_clock(); Chris@87: #endif Chris@87: \tcapi_return = PyObject_CallObject(#name#_capi,(PyObject *)capi_arglist); Chris@87: #ifdef F2PY_REPORT_ATEXIT Chris@87: f2py_cb_stop_call_clock(); Chris@87: #endif Chris@87: \tCFUNCSMESSPY(\"cb:capi_return=\",capi_return); Chris@87: \tif (capi_return == NULL) { Chris@87: \t\tfprintf(stderr,\"capi_return is NULL\\n\"); Chris@87: \t\tgoto capi_fail; Chris@87: \t} Chris@87: \tif (capi_return == Py_None) { Chris@87: \t\tPy_DECREF(capi_return); Chris@87: \t\tcapi_return = Py_BuildValue(\"()\"); Chris@87: \t} Chris@87: \telse if (!PyTuple_Check(capi_return)) { Chris@87: \t\tcapi_return = Py_BuildValue(\"(N)\",capi_return); Chris@87: \t} Chris@87: \tcapi_j = PyTuple_Size(capi_return); Chris@87: \tcapi_i = 0; Chris@87: #frompyobj# Chris@87: \tCFUNCSMESS(\"cb:#name#:successful\\n\"); Chris@87: \tPy_DECREF(capi_return); Chris@87: #ifdef F2PY_REPORT_ATEXIT Chris@87: f2py_cb_stop_clock(); Chris@87: #endif Chris@87: \tgoto capi_return_pt; Chris@87: capi_fail: Chris@87: \tfprintf(stderr,\"Call-back #name# failed.\\n\"); Chris@87: \tPy_XDECREF(capi_return); Chris@87: \tif (capi_longjmp_ok) Chris@87: \t\tlongjmp(#name#_jmpbuf,-1); Chris@87: capi_return_pt: Chris@87: \t; Chris@87: #return# Chris@87: } Chris@87: #endtitle# Chris@87: """, Chris@87: 'need':['setjmp.h', 'CFUNCSMESS'], Chris@87: 'maxnofargs':'#maxnofargs#', Chris@87: 'nofoptargs':'#nofoptargs#', Chris@87: 'docstr':"""\ Chris@87: \tdef #argname#(#docsignature#): return #docreturn#\\n\\ Chris@87: #docstrsigns#""", Chris@87: 'latexdocstr':""" Chris@87: {{}\\verb@def #argname#(#latexdocsignature#): return #docreturn#@{}} Chris@87: #routnote# Chris@87: Chris@87: #latexdocstrsigns#""", Chris@87: 'docstrshort':'def #argname#(#docsignature#): return #docreturn#' Chris@87: } Chris@87: cb_rout_rules=[ Chris@87: {# Init Chris@87: 'separatorsfor': {'decl': '\n', Chris@87: 'args': ',', 'optargs': '', 'pyobjfrom': '\n', 'freemem': '\n', Chris@87: 'args_td': ',', 'optargs_td': '', Chris@87: 'args_nm': ',', 'optargs_nm': '', Chris@87: 'frompyobj': '\n', 'setdims': '\n', Chris@87: 'docstrsigns': '\\n"\n"', Chris@87: 'latexdocstrsigns': '\n', Chris@87: 'latexdocstrreq': '\n', 'latexdocstropt': '\n', Chris@87: 'latexdocstrout': '\n', 'latexdocstrcbs': '\n', Chris@87: }, Chris@87: 'decl': '/*decl*/', 'pyobjfrom': '/*pyobjfrom*/', 'frompyobj': '/*frompyobj*/', Chris@87: 'args': [], 'optargs': '', 'return': '', 'strarglens': '', 'freemem': '/*freemem*/', Chris@87: 'args_td': [], 'optargs_td': '', 'strarglens_td': '', Chris@87: 'args_nm': [], 'optargs_nm': '', 'strarglens_nm': '', Chris@87: 'noargs': '', Chris@87: 'setdims': '/*setdims*/', Chris@87: 'docstrsigns': '', 'latexdocstrsigns': '', Chris@87: 'docstrreq': '\tRequired arguments:', Chris@87: 'docstropt': '\tOptional arguments:', Chris@87: 'docstrout': '\tReturn objects:', Chris@87: 'docstrcbs': '\tCall-back functions:', Chris@87: 'docreturn': '', 'docsign': '', 'docsignopt': '', Chris@87: 'latexdocstrreq': '\\noindent Required arguments:', Chris@87: 'latexdocstropt': '\\noindent Optional arguments:', Chris@87: 'latexdocstrout': '\\noindent Return objects:', Chris@87: 'latexdocstrcbs': '\\noindent Call-back functions:', Chris@87: 'routnote': {hasnote:'--- #note#',l_not(hasnote):''}, Chris@87: }, { # Function Chris@87: 'decl':'\t#ctype# return_value;', Chris@87: 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting return_value->");'}, Chris@87: '\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");', Chris@87: {debugcapi:'\tfprintf(stderr,"#showvalueformat#.\\n",return_value);'} Chris@87: ], Chris@87: 'need':['#ctype#_from_pyobj', {debugcapi:'CFUNCSMESS'}, 'GETSCALARFROMPYTUPLE'], Chris@87: 'return':'\treturn return_value;', Chris@87: '_check':l_and(isfunction, l_not(isstringfunction), l_not(iscomplexfunction)) Chris@87: }, Chris@87: {# String function Chris@87: 'pyobjfrom':{debugcapi:'\tfprintf(stderr,"debug-capi:cb:#name#:%d:\\n",return_value_len);'}, Chris@87: 'args':'#ctype# return_value,int return_value_len', Chris@87: 'args_nm':'return_value,&return_value_len', Chris@87: 'args_td':'#ctype# ,int', Chris@87: 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting return_value->\\"");'}, Chris@87: """\tif (capi_j>capi_i) Chris@87: \t\tGETSTRFROMPYTUPLE(capi_return,capi_i++,return_value,return_value_len);""", Chris@87: {debugcapi:'\tfprintf(stderr,"#showvalueformat#\\".\\n",return_value);'} Chris@87: ], Chris@87: 'need':['#ctype#_from_pyobj', {debugcapi:'CFUNCSMESS'}, Chris@87: 'string.h', 'GETSTRFROMPYTUPLE'], Chris@87: 'return':'return;', Chris@87: '_check':isstringfunction Chris@87: }, Chris@87: {# Complex function Chris@87: 'optargs':""" Chris@87: #ifndef F2PY_CB_RETURNCOMPLEX Chris@87: #ctype# *return_value Chris@87: #endif Chris@87: """, Chris@87: 'optargs_nm':""" Chris@87: #ifndef F2PY_CB_RETURNCOMPLEX Chris@87: return_value Chris@87: #endif Chris@87: """, Chris@87: 'optargs_td':""" Chris@87: #ifndef F2PY_CB_RETURNCOMPLEX Chris@87: #ctype# * Chris@87: #endif Chris@87: """, Chris@87: 'decl':""" Chris@87: #ifdef F2PY_CB_RETURNCOMPLEX Chris@87: \t#ctype# return_value; Chris@87: #endif Chris@87: """, Chris@87: 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting return_value->");'}, Chris@87: """\ Chris@87: \tif (capi_j>capi_i) Chris@87: #ifdef F2PY_CB_RETURNCOMPLEX Chris@87: \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\"); Chris@87: #else Chris@87: \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\"); Chris@87: #endif Chris@87: """, Chris@87: {debugcapi:""" Chris@87: #ifdef F2PY_CB_RETURNCOMPLEX Chris@87: \tfprintf(stderr,\"#showvalueformat#.\\n\",(return_value).r,(return_value).i); Chris@87: #else Chris@87: \tfprintf(stderr,\"#showvalueformat#.\\n\",(*return_value).r,(*return_value).i); Chris@87: #endif Chris@87: Chris@87: """} Chris@87: ], Chris@87: 'return':""" Chris@87: #ifdef F2PY_CB_RETURNCOMPLEX Chris@87: \treturn return_value; Chris@87: #else Chris@87: \treturn; Chris@87: #endif Chris@87: """, Chris@87: 'need':['#ctype#_from_pyobj', {debugcapi:'CFUNCSMESS'}, Chris@87: 'string.h', 'GETSCALARFROMPYTUPLE', '#ctype#'], Chris@87: '_check':iscomplexfunction Chris@87: }, Chris@87: {'docstrout':'\t\t#pydocsignout#', Chris@87: 'latexdocstrout':['\\item[]{{}\\verb@#pydocsignout#@{}}', Chris@87: {hasnote:'--- #note#'}], Chris@87: 'docreturn':'#rname#,', Chris@87: '_check':isfunction}, Chris@87: {'_check':issubroutine,'return':'return;'} Chris@87: ] Chris@87: Chris@87: cb_arg_rules=[ Chris@87: { # Doc Chris@87: 'docstropt':{l_and(isoptional, isintent_nothide):'\t\t#pydocsign#'}, Chris@87: 'docstrreq':{l_and(isrequired, isintent_nothide):'\t\t#pydocsign#'}, Chris@87: 'docstrout':{isintent_out:'\t\t#pydocsignout#'}, Chris@87: 'latexdocstropt':{l_and(isoptional, isintent_nothide):['\\item[]{{}\\verb@#pydocsign#@{}}', Chris@87: {hasnote:'--- #note#'}]}, Chris@87: 'latexdocstrreq':{l_and(isrequired, isintent_nothide):['\\item[]{{}\\verb@#pydocsign#@{}}', Chris@87: {hasnote:'--- #note#'}]}, Chris@87: 'latexdocstrout':{isintent_out:['\\item[]{{}\\verb@#pydocsignout#@{}}', Chris@87: {l_and(hasnote, isintent_hide):'--- #note#', Chris@87: l_and(hasnote, isintent_nothide):'--- See above.'}]}, Chris@87: 'docsign':{l_and(isrequired, isintent_nothide):'#varname#,'}, Chris@87: 'docsignopt':{l_and(isoptional, isintent_nothide):'#varname#,'}, Chris@87: 'depend':'' Chris@87: }, Chris@87: { Chris@87: 'args': { Chris@87: l_and (isscalar, isintent_c):'#ctype# #varname_i#', Chris@87: l_and (isscalar, l_not(isintent_c)):'#ctype# *#varname_i#_cb_capi', Chris@87: isarray:'#ctype# *#varname_i#', Chris@87: isstring:'#ctype# #varname_i#' Chris@87: }, Chris@87: 'args_nm': { Chris@87: l_and (isscalar, isintent_c):'#varname_i#', Chris@87: l_and (isscalar, l_not(isintent_c)):'#varname_i#_cb_capi', Chris@87: isarray:'#varname_i#', Chris@87: isstring:'#varname_i#' Chris@87: }, Chris@87: 'args_td': { Chris@87: l_and (isscalar, isintent_c):'#ctype#', Chris@87: l_and (isscalar, l_not(isintent_c)):'#ctype# *', Chris@87: isarray:'#ctype# *', Chris@87: isstring:'#ctype#' Chris@87: }, Chris@87: 'strarglens': {isstring:',int #varname_i#_cb_len'}, # untested with multiple args Chris@87: 'strarglens_td': {isstring:',int'}, # untested with multiple args Chris@87: 'strarglens_nm': {isstring:',#varname_i#_cb_len'}, # untested with multiple args Chris@87: }, Chris@87: { # Scalars Chris@87: 'decl':{l_not(isintent_c):'\t#ctype# #varname_i#=(*#varname_i#_cb_capi);'}, Chris@87: 'error': {l_and(isintent_c, isintent_out, Chris@87: throw_error('intent(c,out) is forbidden for callback scalar arguments')):\ Chris@87: ''}, Chris@87: 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting #varname#->");'}, Chris@87: {isintent_out:'\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");'}, Chris@87: {l_and(debugcapi, l_and(l_not(iscomplex), isintent_c)):'\tfprintf(stderr,"#showvalueformat#.\\n",#varname_i#);'}, Chris@87: {l_and(debugcapi, l_and(l_not(iscomplex), l_not(isintent_c))):'\tfprintf(stderr,"#showvalueformat#.\\n",*#varname_i#_cb_capi);'}, Chris@87: {l_and(debugcapi, l_and(iscomplex, isintent_c)):'\tfprintf(stderr,"#showvalueformat#.\\n",(#varname_i#).r,(#varname_i#).i);'}, Chris@87: {l_and(debugcapi, l_and(iscomplex, l_not(isintent_c))):'\tfprintf(stderr,"#showvalueformat#.\\n",(*#varname_i#_cb_capi).r,(*#varname_i#_cb_capi).i);'}, Chris@87: ], Chris@87: 'need':[{isintent_out:['#ctype#_from_pyobj', 'GETSCALARFROMPYTUPLE']}, Chris@87: {debugcapi:'CFUNCSMESS'}], Chris@87: '_check':isscalar Chris@87: }, { Chris@87: 'pyobjfrom':[{isintent_in:"""\ Chris@87: \tif (#name#_nofargs>capi_i) Chris@87: \t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyobj_from_#ctype#1(#varname_i#))) Chris@87: \t\t\tgoto capi_fail;"""}, Chris@87: {isintent_inout:"""\ Chris@87: \tif (#name#_nofargs>capi_i) Chris@87: \t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyarr_from_p_#ctype#1(#varname_i#_cb_capi))) Chris@87: \t\t\tgoto capi_fail;"""}], Chris@87: 'need':[{isintent_in:'pyobj_from_#ctype#1'}, Chris@87: {isintent_inout:'pyarr_from_p_#ctype#1'}, Chris@87: {iscomplex:'#ctype#'}], Chris@87: '_check':l_and(isscalar, isintent_nothide), Chris@87: '_optional':'' Chris@87: }, {# String Chris@87: 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting #varname#->\\"");'}, Chris@87: """\tif (capi_j>capi_i) Chris@87: \t\tGETSTRFROMPYTUPLE(capi_return,capi_i++,#varname_i#,#varname_i#_cb_len);""", Chris@87: {debugcapi:'\tfprintf(stderr,"#showvalueformat#\\":%d:.\\n",#varname_i#,#varname_i#_cb_len);'}, Chris@87: ], Chris@87: 'need':['#ctype#', 'GETSTRFROMPYTUPLE', Chris@87: {debugcapi:'CFUNCSMESS'}, 'string.h'], Chris@87: '_check':l_and(isstring, isintent_out) Chris@87: }, { Chris@87: 'pyobjfrom':[{debugcapi:'\tfprintf(stderr,"debug-capi:cb:#varname#=\\"#showvalueformat#\\":%d:\\n",#varname_i#,#varname_i#_cb_len);'}, Chris@87: {isintent_in:"""\ Chris@87: \tif (#name#_nofargs>capi_i) Chris@87: \t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyobj_from_#ctype#1size(#varname_i#,#varname_i#_cb_len))) Chris@87: \t\t\tgoto capi_fail;"""}, Chris@87: {isintent_inout:"""\ Chris@87: \tif (#name#_nofargs>capi_i) { Chris@87: \t\tint #varname_i#_cb_dims[] = {#varname_i#_cb_len}; Chris@87: \t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyarr_from_p_#ctype#1(#varname_i#,#varname_i#_cb_dims))) Chris@87: \t\t\tgoto capi_fail; Chris@87: \t}"""}], Chris@87: 'need':[{isintent_in:'pyobj_from_#ctype#1size'}, Chris@87: {isintent_inout:'pyarr_from_p_#ctype#1'}], Chris@87: '_check':l_and(isstring, isintent_nothide), Chris@87: '_optional':'' Chris@87: }, Chris@87: # Array ... Chris@87: { Chris@87: 'decl':'\tnpy_intp #varname_i#_Dims[#rank#] = {#rank*[-1]#};', Chris@87: 'setdims':'\t#cbsetdims#;', Chris@87: '_check':isarray, Chris@87: '_depend':'' Chris@87: }, Chris@87: { Chris@87: 'pyobjfrom': [{debugcapi:'\tfprintf(stderr,"debug-capi:cb:#varname#\\n");'}, Chris@87: {isintent_c: """\ Chris@87: \tif (#name#_nofargs>capi_i) { Chris@87: \t\tPyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,0,NPY_CARRAY,NULL); /*XXX: Hmm, what will destroy this array??? */ Chris@87: """, Chris@87: l_not(isintent_c): """\ Chris@87: \tif (#name#_nofargs>capi_i) { Chris@87: \t\tPyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,0,NPY_FARRAY,NULL); /*XXX: Hmm, what will destroy this array??? */ Chris@87: """, Chris@87: }, Chris@87: """ Chris@87: \t\tif (tmp_arr==NULL) Chris@87: \t\t\tgoto capi_fail; Chris@87: \t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,(PyObject *)tmp_arr)) Chris@87: \t\t\tgoto capi_fail; Chris@87: }"""], Chris@87: '_check': l_and(isarray, isintent_nothide, l_or(isintent_in, isintent_inout)), Chris@87: '_optional': '', Chris@87: }, { Chris@87: 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting #varname#->");'}, Chris@87: """\tif (capi_j>capi_i) { Chris@87: \t\tPyArrayObject *rv_cb_arr = NULL; Chris@87: \t\tif ((capi_tmp = PyTuple_GetItem(capi_return,capi_i++))==NULL) goto capi_fail; Chris@87: \t\trv_cb_arr = array_from_pyobj(#atype#,#varname_i#_Dims,#rank#,F2PY_INTENT_IN""", Chris@87: {isintent_c:'|F2PY_INTENT_C'}, Chris@87: """,capi_tmp); Chris@87: \t\tif (rv_cb_arr == NULL) { Chris@87: \t\t\tfprintf(stderr,\"rv_cb_arr is NULL\\n\"); Chris@87: \t\t\tgoto capi_fail; Chris@87: \t\t} Chris@87: \t\tMEMCOPY(#varname_i#,rv_cb_arr->data,PyArray_NBYTES(rv_cb_arr)); Chris@87: \t\tif (capi_tmp != (PyObject *)rv_cb_arr) { Chris@87: \t\t\tPy_DECREF(rv_cb_arr); Chris@87: \t\t} Chris@87: \t}""", Chris@87: {debugcapi:'\tfprintf(stderr,"<-.\\n");'}, Chris@87: ], Chris@87: 'need':['MEMCOPY', {iscomplexarray:'#ctype#'}], Chris@87: '_check':l_and(isarray, isintent_out) Chris@87: }, { Chris@87: 'docreturn':'#varname#,', Chris@87: '_check':isintent_out Chris@87: } Chris@87: ] Chris@87: Chris@87: ################## Build call-back module ############# Chris@87: cb_map={} Chris@87: def buildcallbacks(m): Chris@87: global cb_map Chris@87: cb_map[m['name']]=[] Chris@87: for bi in m['body']: Chris@87: if bi['block']=='interface': Chris@87: for b in bi['body']: Chris@87: if b: Chris@87: buildcallback(b, m['name']) Chris@87: else: Chris@87: errmess('warning: empty body for %s\n' % (m['name'])) Chris@87: Chris@87: def buildcallback(rout, um): Chris@87: global cb_map Chris@87: from . import capi_maps Chris@87: Chris@87: outmess('\tConstructing call-back function "cb_%s_in_%s"\n'%(rout['name'], um)) Chris@87: args, depargs=getargs(rout) Chris@87: capi_maps.depargs=depargs Chris@87: var=rout['vars'] Chris@87: vrd=capi_maps.cb_routsign2map(rout, um) Chris@87: rd=dictappend({}, vrd) Chris@87: cb_map[um].append([rout['name'], rd['name']]) Chris@87: for r in cb_rout_rules: Chris@87: if ('_check' in r and r['_check'](rout)) or ('_check' not in r): Chris@87: ar=applyrules(r, vrd, rout) Chris@87: rd=dictappend(rd, ar) Chris@87: savevrd={} Chris@87: for i, a in enumerate(args): Chris@87: vrd=capi_maps.cb_sign2map(a, var[a], index=i) Chris@87: savevrd[a]=vrd Chris@87: for r in cb_arg_rules: Chris@87: if '_depend' in r: Chris@87: continue Chris@87: if '_optional' in r and isoptional(var[a]): Chris@87: continue Chris@87: if ('_check' in r and r['_check'](var[a])) or ('_check' not in r): Chris@87: ar=applyrules(r, vrd, var[a]) Chris@87: rd=dictappend(rd, ar) Chris@87: if '_break' in r: Chris@87: break Chris@87: for a in args: Chris@87: vrd=savevrd[a] Chris@87: for r in cb_arg_rules: Chris@87: if '_depend' in r: Chris@87: continue Chris@87: if ('_optional' not in r) or ('_optional' in r and isrequired(var[a])): Chris@87: continue Chris@87: if ('_check' in r and r['_check'](var[a])) or ('_check' not in r): Chris@87: ar=applyrules(r, vrd, var[a]) Chris@87: rd=dictappend(rd, ar) Chris@87: if '_break' in r: Chris@87: break Chris@87: for a in depargs: Chris@87: vrd=savevrd[a] Chris@87: for r in cb_arg_rules: Chris@87: if '_depend' not in r: Chris@87: continue Chris@87: if '_optional' in r: Chris@87: continue Chris@87: if ('_check' in r and r['_check'](var[a])) or ('_check' not in r): Chris@87: ar=applyrules(r, vrd, var[a]) Chris@87: rd=dictappend(rd, ar) Chris@87: if '_break' in r: Chris@87: break Chris@87: if 'args' in rd and 'optargs' in rd: Chris@87: if isinstance(rd['optargs'], list): Chris@87: rd['optargs']=rd['optargs']+[""" Chris@87: #ifndef F2PY_CB_RETURNCOMPLEX Chris@87: , Chris@87: #endif Chris@87: """] Chris@87: rd['optargs_nm']=rd['optargs_nm']+[""" Chris@87: #ifndef F2PY_CB_RETURNCOMPLEX Chris@87: , Chris@87: #endif Chris@87: """] Chris@87: rd['optargs_td']=rd['optargs_td']+[""" Chris@87: #ifndef F2PY_CB_RETURNCOMPLEX Chris@87: , Chris@87: #endif Chris@87: """] Chris@87: if isinstance(rd['docreturn'], list): Chris@87: rd['docreturn']=stripcomma(replace('#docreturn#', {'docreturn':rd['docreturn']})) Chris@87: optargs=stripcomma(replace('#docsignopt#', Chris@87: {'docsignopt':rd['docsignopt']} Chris@87: )) Chris@87: if optargs=='': Chris@87: rd['docsignature']=stripcomma(replace('#docsign#', {'docsign':rd['docsign']})) Chris@87: else: Chris@87: rd['docsignature']=replace('#docsign#[#docsignopt#]', Chris@87: {'docsign': rd['docsign'], Chris@87: 'docsignopt': optargs, Chris@87: }) Chris@87: rd['latexdocsignature']=rd['docsignature'].replace('_', '\\_') Chris@87: rd['latexdocsignature']=rd['latexdocsignature'].replace(',', ', ') Chris@87: rd['docstrsigns']=[] Chris@87: rd['latexdocstrsigns']=[] Chris@87: for k in ['docstrreq', 'docstropt', 'docstrout', 'docstrcbs']: Chris@87: if k in rd and isinstance(rd[k], list): Chris@87: rd['docstrsigns']=rd['docstrsigns']+rd[k] Chris@87: k='latex'+k Chris@87: if k in rd and isinstance(rd[k], list): Chris@87: rd['latexdocstrsigns']=rd['latexdocstrsigns']+rd[k][0:1]+\ Chris@87: ['\\begin{description}']+rd[k][1:]+\ Chris@87: ['\\end{description}'] Chris@87: if 'args' not in rd: Chris@87: rd['args']='' Chris@87: rd['args_td']='' Chris@87: rd['args_nm']='' Chris@87: if not (rd.get('args') or rd.get('optargs') or rd.get('strarglens')): Chris@87: rd['noargs'] = 'void' Chris@87: Chris@87: ar=applyrules(cb_routine_rules, rd) Chris@87: cfuncs.callbacks[rd['name']]=ar['body'] Chris@87: if isinstance(ar['need'], str): Chris@87: ar['need']=[ar['need']] Chris@87: Chris@87: if 'need' in rd: Chris@87: for t in cfuncs.typedefs.keys(): Chris@87: if t in rd['need']: Chris@87: ar['need'].append(t) Chris@87: Chris@87: cfuncs.typedefs_generated[rd['name']+'_typedef'] = ar['cbtypedefs'] Chris@87: ar['need'].append(rd['name']+'_typedef') Chris@87: cfuncs.needs[rd['name']]=ar['need'] Chris@87: Chris@87: capi_maps.lcb2_map[rd['name']]={'maxnofargs':ar['maxnofargs'], Chris@87: 'nofoptargs':ar['nofoptargs'], Chris@87: 'docstr':ar['docstr'], Chris@87: 'latexdocstr':ar['latexdocstr'], Chris@87: 'argname':rd['argname'] Chris@87: } Chris@87: outmess('\t %s\n'%(ar['docstrshort'])) Chris@87: #print ar['body'] Chris@87: return Chris@87: ################## Build call-back function #############