__all__ = ['PythonCAPISubProgram'] import sys from parser.api import TypeDecl, TypeStmt, Module from wrapper_base import * from py_wrap_type import * class PythonCAPISubProgram(WrapperBase): """ Fortran subprogram hooks. """ header_template_f77 = '''\ #define %(name)s_f F_FUNC(%(name)s, %(NAME)s) ''' extern_template_f77 = '''\ extern void %(name)s_f(%(ctype_args_f_clist)s); ''' objdecl_template_doc = '''\ static char %(cname)s__doc[] = ""; ''' module_method_template = '''\ {"%(pyname)s", (PyCFunction)%(cname)s, METH_VARARGS | METH_KEYWORDS, %(cname)s__doc},''' capi_code_template = '''\ static PyObject* %(cname)s(PyObject *capi_self, PyObject *capi_args, PyObject *capi_keywds) { PyObject * volatile capi_buildvalue = NULL; volatile int f2py_success = 1; %(decl_list)s static char *capi_kwlist[] = {%(kw_clist+optkw_clist+extrakw_clist+["NULL"])s}; if (PyArg_ParseTupleAndKeywords(capi_args,capi_keywds, "%(pyarg_format_elist)s", %(["capi_kwlist"]+pyarg_obj_clist)s)) { %(frompyobj_list)s %(call_list)s f2py_success = !PyErr_Occurred(); if (f2py_success) { %(pyobjfrom_list)s capi_buildvalue = Py_BuildValue("%(return_format_elist)s" %(return_obj_clist)s); %(clean_pyobjfrom_list)s } %(clean_call_list)s %(clean_frompyobj_list)s } return capi_buildvalue; } ''' header_template_module = ''' #define %(name)s_f (*%(name)s_func_ptr) #define %(init_func)s_f F_FUNC(%(init_func)s, %(INIT_FUNC)s) ''' typedef_template_module = ''' typedef void (*%(name)s_functype)(%(ctype_args_f_clist)s); typedef void (*%(init_func)s_c_functype)(%(name)s_functype); ''' extern_template_module = '''\ extern void %(init_func)s_f(%(init_func)s_c_functype); static %(name)s_functype %(name)s_func_ptr; ''' objdecl_template_module = ''' ''' fortran_code_template_module = ''' subroutine %(init_func)s(init_func_c) use %(mname)s external init_func_c call init_func_c(%(name)s) end ''' c_code_template_module = ''' static void %(init_func)s_c(%(name)s_functype func_ptr) { %(name)s_func_ptr = func_ptr; } ''' module_init_template_module = ''' %(init_func)s_f(%(init_func)s_c); ''' def __init__(self, parent, block): WrapperBase.__init__(self) self.name = name = pyname = block.name self.cname = cname = '%s_%s' % (parent.cname,name) defined = parent.defined_capi_codes if cname in defined: return defined.append(cname) self.info('Generating interface for %s %s: %s' % (parent.modulename, block.__class__.__name__, cname)) self.parent = parent if pyname.startswith('f2pywrap_'): pyname = pyname[9:] self.pyname = pyname self.header_template = '' self.extern_template = '' self.module_init_template = '' self.typedef_template = '' self.c_code_template = '' self.objdecl_template = '' self.fortran_code_template = '' WrapperCPPMacro(parent, 'F_FUNC') if isinstance(block.parent, Module): self.mname = block.parent.name self.init_func = '%s_init' % (name) self.typedef_template += self.typedef_template_module self.header_template += self.header_template_module self.fortran_code_template += self.fortran_code_template_module self.module_init_template += self.module_init_template_module self.objdecl_template += self.objdecl_template_module self.c_code_template += self.c_code_template_module self.extern_template += self.extern_template_module else: self.extern_template += self.extern_template_f77 self.header_template += self.header_template_f77 self.objdecl_template += self.objdecl_template_doc self.decl_list = [] self.kw_list = [] self.optkw_list = [] self.extrakw_list = [] self.pyarg_format_list = [] self.pyarg_obj_list = [] self.frompyobj_list = [] self.call_list = [] self.pyobjfrom_list = [] self.return_format_list = [] self.return_obj_list = [] self.buildvalue_list = [] self.clean_pyobjfrom_list = [] self.clean_call_list = [] self.clean_frompyobj_list = [] args_f = [] extra_args_f = [] ctype_args_f = [] extra_ctype_args_f = [] argindex = -1 for argname in block.args: argindex += 1 var = block.a.variables[argname] typedecl = var.get_typedecl() PythonCAPIType(parent, typedecl) ti = PyTypeInterface(typedecl) if var.is_intent_in(): self.kw_list.append('"%s"' % (argname)) if var.is_scalar(): if isinstance(typedecl, TypeStmt): if var.is_intent_in(): self.pyarg_format_list.append('O&') self.pyarg_obj_list.append('\npyobj_to_%s_inplace, &%s' % (ti.ctype, argname)) else: self.frompyobj_list.append('%s = (%s*)pyobj_from_%s(NULL);' % (argname,ti.otype,ti.ctype)) if not var.is_intent_out(): self.clean_frompyobj_list.append('Py_DECREF(%s);' % (argname)) self.decl_list.append('%s* %s = NULL;' % (ti.otype, argname)) args_f.append('%s->data' % (argname)) # is_scalar ctype_args_f.append(ti.ctype) else: if var.is_intent_in(): self.pyarg_format_list.append('O&') self.pyarg_obj_list.append('\npyobj_to_%s, &%s' % (ti.ctype, argname)) assert not isinstance(typedecl, TypeDecl) if ti.ctype=='f2py_string0': if not var.is_intent_in(): assert not var.is_intent_out(),'intent(out) not implemented for "%s"' % (var) self.decl_list.append('%s %s = {NULL,0};' % (ti.ctype, argname)) args_f.append('%s.data' % argname) # is_scalar ctype_args_f.append('char*') extra_ctype_args_f.append('int') extra_args_f.append('%s.len' % argname) self.clean_frompyobj_list.append(\ 'if (%s.len) free(%s.data);' % (argname,argname)) else: self.decl_list.append('%s %s;' % (ti.ctype, argname)) args_f.append('&'+argname) # is_scalar ctype_args_f.append(ti.ctype+'*') if var.is_intent_out(): # and is_scalar if isinstance(typedecl, TypeStmt): self.return_format_list.append('N') self.return_obj_list.append('\n%s' % (argname)) else: self.return_format_list.append('O&') self.return_obj_list.append('\npyobj_from_%s, &%s' % (ti.ctype, argname)) else: print `ti,var.dimension,var.bounds` assert var.is_scalar(),'array support not implemented: "%s"' % (var) self.call_list.append('%s_f(%s);' % (name,', '.join(args_f+extra_args_f))) self.ctype_args_f_list = ctype_args_f + extra_ctype_args_f if not self.ctype_args_f_list: self.ctype_args_f_list.append('void') self.clean_pyobjfrom_list.reverse() self.clean_call_list.reverse() self.clean_frompyobj_list.reverse() if self.return_obj_list: self.return_obj_list.insert(0,'') parent.apply_templates(self) return