Spaces:
Paused
Paused
#!/usr/bin/env python3 | |
""" | |
Rules for building C/API module with f2py2e. | |
Copyright 1999,2000 Pearu Peterson all rights reserved, | |
Pearu Peterson <[email protected]> | |
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 | |
""" | |
__version__ = "$Revision: 1.16 $"[10:-1] | |
f2py_version = 'See `f2py -v`' | |
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 = var2fixfortran(vars, name, newname, f90mode) | |
if l[:13] == 'character*(*)': | |
if f90mode: | |
l = 'character(len=10)' + l[13:] | |
else: | |
l = 'character*10' + l[13:] | |
charselect = vars[name]['charselector'] | |
if charselect.get('*', '') == '(*)': | |
charselect['*'] = '10' | |
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)) | |
l = l + ', ' + 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(l) | |
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, '' | |