| Viewing file:  func2subr.py (9.54 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
#!/usr/bin/env python3"""
 
 Rules for building C/API module with f2py2e.
 
 Copyright 1999,2000 Pearu Peterson all rights reserved,
 Pearu Peterson <pearu@ioc.ee>
 Permission to use, modify, and distribute this software is given under the
 terms of the NumPy License.
 
 NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
 $Date: 2004/11/26 11:13:06 $
 Pearu Peterson
 
 """
 import copy
 
 from .auxfuncs import (
 getfortranname, isexternal, isfunction, isfunction_wrap, isintent_in,
 isintent_out, islogicalfunction, ismoduleroutine, isscalar,
 issubroutine, issubroutine_wrap, outmess, show
 )
 
 
 def var2fixfortran(vars, a, fa=None, f90mode=None):
 if fa is None:
 fa = a
 if a not in vars:
 show(vars)
 outmess('var2fixfortran: No definition for argument "%s".\n' % a)
 return ''
 if 'typespec' not in vars[a]:
 show(vars[a])
 outmess('var2fixfortran: No typespec for argument "%s".\n' % a)
 return ''
 vardef = vars[a]['typespec']
 if vardef == 'type' and 'typename' in vars[a]:
 vardef = '%s(%s)' % (vardef, vars[a]['typename'])
 selector = {}
 lk = ''
 if 'kindselector' in vars[a]:
 selector = vars[a]['kindselector']
 lk = 'kind'
 elif 'charselector' in vars[a]:
 selector = vars[a]['charselector']
 lk = 'len'
 if '*' in selector:
 if f90mode:
 if selector['*'] in ['*', ':', '(*)']:
 vardef = '%s(len=*)' % (vardef)
 else:
 vardef = '%s(%s=%s)' % (vardef, lk, selector['*'])
 else:
 if selector['*'] in ['*', ':']:
 vardef = '%s*(%s)' % (vardef, selector['*'])
 else:
 vardef = '%s*%s' % (vardef, selector['*'])
 else:
 if 'len' in selector:
 vardef = '%s(len=%s' % (vardef, selector['len'])
 if 'kind' in selector:
 vardef = '%s,kind=%s)' % (vardef, selector['kind'])
 else:
 vardef = '%s)' % (vardef)
 elif 'kind' in selector:
 vardef = '%s(kind=%s)' % (vardef, selector['kind'])
 
 vardef = '%s %s' % (vardef, fa)
 if 'dimension' in vars[a]:
 vardef = '%s(%s)' % (vardef, ','.join(vars[a]['dimension']))
 return vardef
 
 
 def createfuncwrapper(rout, signature=0):
 assert isfunction(rout)
 
 extra_args = []
 vars = rout['vars']
 for a in rout['args']:
 v = rout['vars'][a]
 for i, d in enumerate(v.get('dimension', [])):
 if d == ':':
 dn = 'f2py_%s_d%s' % (a, i)
 dv = dict(typespec='integer', intent=['hide'])
 dv['='] = 'shape(%s, %s)' % (a, i)
 extra_args.append(dn)
 vars[dn] = dv
 v['dimension'][i] = dn
 rout['args'].extend(extra_args)
 need_interface = bool(extra_args)
 
 ret = ['']
 
 def add(line, ret=ret):
 ret[0] = '%s\n      %s' % (ret[0], line)
 name = rout['name']
 fortranname = getfortranname(rout)
 f90mode = ismoduleroutine(rout)
 newname = '%sf2pywrap' % (name)
 
 if newname not in vars:
 vars[newname] = vars[name]
 args = [newname] + rout['args'][1:]
 else:
 args = [newname] + rout['args']
 
 l_tmpl = var2fixfortran(vars, name, '@@@NAME@@@', f90mode)
 if l_tmpl[:13] == 'character*(*)':
 if f90mode:
 l_tmpl = 'character(len=10)' + l_tmpl[13:]
 else:
 l_tmpl = 'character*10' + l_tmpl[13:]
 charselect = vars[name]['charselector']
 if charselect.get('*', '') == '(*)':
 charselect['*'] = '10'
 
 l1 = l_tmpl.replace('@@@NAME@@@', newname)
 rl = None
 
 sargs = ', '.join(args)
 if f90mode:
 # gh-23598 fix warning
 # Essentially, this gets called again with modules where the name of the
 # function is added to the arguments, which is not required, and removed
 sargs = sargs.replace(f"{name}, ", '')
 args = [arg for arg in args if arg != name]
 rout['args'] = args
 add('subroutine f2pywrap_%s_%s (%s)' %
 (rout['modulename'], name, sargs))
 if not signature:
 add('use %s, only : %s' % (rout['modulename'], fortranname))
 else:
 add('subroutine f2pywrap%s (%s)' % (name, sargs))
 if not need_interface:
 add('external %s' % (fortranname))
 rl = l_tmpl.replace('@@@NAME@@@', '') + ' ' + fortranname
 
 if need_interface:
 for line in rout['saved_interface'].split('\n'):
 if line.lstrip().startswith('use ') and '__user__' not in line:
 add(line)
 
 args = args[1:]
 dumped_args = []
 for a in args:
 if isexternal(vars[a]):
 add('external %s' % (a))
 dumped_args.append(a)
 for a in args:
 if a in dumped_args:
 continue
 if isscalar(vars[a]):
 add(var2fixfortran(vars, a, f90mode=f90mode))
 dumped_args.append(a)
 for a in args:
 if a in dumped_args:
 continue
 if isintent_in(vars[a]):
 add(var2fixfortran(vars, a, f90mode=f90mode))
 dumped_args.append(a)
 for a in args:
 if a in dumped_args:
 continue
 add(var2fixfortran(vars, a, f90mode=f90mode))
 
 add(l1)
 if rl is not None:
 add(rl)
 
 if need_interface:
 if f90mode:
 # f90 module already defines needed interface
 pass
 else:
 add('interface')
 add(rout['saved_interface'].lstrip())
 add('end interface')
 
 sargs = ', '.join([a for a in args if a not in extra_args])
 
 if not signature:
 if islogicalfunction(rout):
 add('%s = .not.(.not.%s(%s))' % (newname, fortranname, sargs))
 else:
 add('%s = %s(%s)' % (newname, fortranname, sargs))
 if f90mode:
 add('end subroutine f2pywrap_%s_%s' % (rout['modulename'], name))
 else:
 add('end')
 return ret[0]
 
 
 def createsubrwrapper(rout, signature=0):
 assert issubroutine(rout)
 
 extra_args = []
 vars = rout['vars']
 for a in rout['args']:
 v = rout['vars'][a]
 for i, d in enumerate(v.get('dimension', [])):
 if d == ':':
 dn = 'f2py_%s_d%s' % (a, i)
 dv = dict(typespec='integer', intent=['hide'])
 dv['='] = 'shape(%s, %s)' % (a, i)
 extra_args.append(dn)
 vars[dn] = dv
 v['dimension'][i] = dn
 rout['args'].extend(extra_args)
 need_interface = bool(extra_args)
 
 ret = ['']
 
 def add(line, ret=ret):
 ret[0] = '%s\n      %s' % (ret[0], line)
 name = rout['name']
 fortranname = getfortranname(rout)
 f90mode = ismoduleroutine(rout)
 
 args = rout['args']
 
 sargs = ', '.join(args)
 if f90mode:
 add('subroutine f2pywrap_%s_%s (%s)' %
 (rout['modulename'], name, sargs))
 if not signature:
 add('use %s, only : %s' % (rout['modulename'], fortranname))
 else:
 add('subroutine f2pywrap%s (%s)' % (name, sargs))
 if not need_interface:
 add('external %s' % (fortranname))
 
 if need_interface:
 for line in rout['saved_interface'].split('\n'):
 if line.lstrip().startswith('use ') and '__user__' not in line:
 add(line)
 
 dumped_args = []
 for a in args:
 if isexternal(vars[a]):
 add('external %s' % (a))
 dumped_args.append(a)
 for a in args:
 if a in dumped_args:
 continue
 if isscalar(vars[a]):
 add(var2fixfortran(vars, a, f90mode=f90mode))
 dumped_args.append(a)
 for a in args:
 if a in dumped_args:
 continue
 add(var2fixfortran(vars, a, f90mode=f90mode))
 
 if need_interface:
 if f90mode:
 # f90 module already defines needed interface
 pass
 else:
 add('interface')
 for line in rout['saved_interface'].split('\n'):
 if line.lstrip().startswith('use ') and '__user__' in line:
 continue
 add(line)
 add('end interface')
 
 sargs = ', '.join([a for a in args if a not in extra_args])
 
 if not signature:
 add('call %s(%s)' % (fortranname, sargs))
 if f90mode:
 add('end subroutine f2pywrap_%s_%s' % (rout['modulename'], name))
 else:
 add('end')
 return ret[0]
 
 
 def assubr(rout):
 if isfunction_wrap(rout):
 fortranname = getfortranname(rout)
 name = rout['name']
 outmess('\t\tCreating wrapper for Fortran function "%s"("%s")...\n' % (
 name, fortranname))
 rout = copy.copy(rout)
 fname = name
 rname = fname
 if 'result' in rout:
 rname = rout['result']
 rout['vars'][fname] = rout['vars'][rname]
 fvar = rout['vars'][fname]
 if not isintent_out(fvar):
 if 'intent' not in fvar:
 fvar['intent'] = []
 fvar['intent'].append('out')
 flag = 1
 for i in fvar['intent']:
 if i.startswith('out='):
 flag = 0
 break
 if flag:
 fvar['intent'].append('out=%s' % (rname))
 rout['args'][:] = [fname] + rout['args']
 return rout, createfuncwrapper(rout)
 if issubroutine_wrap(rout):
 fortranname = getfortranname(rout)
 name = rout['name']
 outmess('\t\tCreating wrapper for Fortran subroutine "%s"("%s")...\n'
 % (name, fortranname))
 rout = copy.copy(rout)
 return rout, createsubrwrapper(rout)
 return rout, ''
 
 |