[Numpy-svn] r3250 - in trunk/numpy/f2py/lib: . parser
numpy-svn at scipy.org
numpy-svn at scipy.org
Wed Oct 4 05:50:04 EDT 2006
Author: pearu
Date: 2006-10-04 04:49:54 -0500 (Wed, 04 Oct 2006)
New Revision: 3250
Added:
trunk/numpy/f2py/lib/py_wrap.py
Modified:
trunk/numpy/f2py/lib/main.py
trunk/numpy/f2py/lib/parser/api.py
trunk/numpy/f2py/lib/parser/base_classes.py
trunk/numpy/f2py/lib/parser/block_statements.py
trunk/numpy/f2py/lib/parser/parsefortran.py
trunk/numpy/f2py/lib/parser/statements.py
trunk/numpy/f2py/lib/python_wrapper.py
Log:
F2PY G3: exposed wrappers via f2py script. A working example: wrap F90 module containing derived type with scalar components.
Modified: trunk/numpy/f2py/lib/main.py
===================================================================
--- trunk/numpy/f2py/lib/main.py 2006-10-03 15:52:44 UTC (rev 3249)
+++ trunk/numpy/f2py/lib/main.py 2006-10-04 09:49:54 UTC (rev 3250)
@@ -12,7 +12,9 @@
"""
import os
+import re
import sys
+import tempfile
try:
from numpy import __version__ as numpy_version
@@ -44,53 +46,92 @@
"""
-from parser.api import parse, PythonModule, EndStatement
+import re
+import shutil
+from parser.api import parse, PythonModule, EndStatement, Module, Subroutine, Function
-def dump_signature():
- """ Read Fortran files and dump the signatures to file or stdout.
+def get_values(sys_argv, prefix='', suffix='', strip_prefix=False, strip_suffix=False):
"""
- # get signature output
- i = sys.argv.index('-h')
- if len(sys.argv)-1==i:
- signature_output = 'stdout'
- else:
- signature_output = sys.argv[i+1]
- del sys.argv[i+1]
- del sys.argv[i]
+ Return a list of values with pattern
+ <prefix><value><suffix>.
+ The corresponding items will be removed from sys_argv.
+ """
+ match = re.compile(prefix + r'.*' + suffix + '\Z').match
+ ret = [item for item in sys_argv if match(item)]
+ [sys_argv.remove(item) for item in ret]
+ if strip_prefix and prefix:
+ i = len(prefix)
+ ret = [item[i:] for item in ret]
+ if strip_suffix and suffix:
+ i = len(suffix)
+ ret = [item[:-i] for item in ret]
+ return ret
- # get module name
+def get_option(sys_argv, option, default_return = None):
+ """
+ Return True if sys_argv has <option>.
+ If <option> is not in sys_argv, return default_return.
+ <option> (when present) will be removed from sys_argv.
+ """
try:
- i = sys.argv.index('-m')
+ i = sys_argv.index(option)
except ValueError:
- i = None
- module_name = 'unknown'
- if i is not None:
- if len(sys.argv)-1==i:
- module_name = 'unspecified'
- else:
- module_name = sys.argv[i+1]
- del sys.argv[i+1]
- del sys.argv[i]
+ return default_return
+ del sys_argv[i]
+ return True
+def get_option_value(sys_argv, option, default_value = None, default_return = None):
+ """
+ Return <value> from
+ sys_argv = [...,<option>,<value>,...]
+ list.
+ If <option> is the last element, return default_value.
+ If <option> is not in sys_argv, return default_return.
+ Both <option> and <value> (when present) will be removed from sys_argv.
+ """
+ try:
+ i = sys_argv.index(option)
+ except ValueError:
+ return default_return
+ if len(sys_argv)-1==i:
+ del sys_argv[i]
+ return default_value
+ value = sys_argv[i+1]
+ del sys_argv[i+1]
+ del sys_argv[i]
+ return value
+
+def get_signature_output(sys_argv):
+ return get_option_value(sys_argv,'-h','stdout')
+
+def dump_signature(sys_argv):
+ """ Read Fortran files and dump the signatures to file or stdout.
+ XXX: Not well tested.
+ """
+ signature_output = get_signature_output(sys_argv)
+
# initialize output stream
if signature_output in ['stdout','stderr']:
output_stream = getattr(sys, signature_output)
+ modulename = get_option_value(sys_argv,'-m','untitled','unknown')
else:
+ name,ext = os.path.splitext(signature_output)
+ if ext != '.pyf':
+ signature_output += '.pyf'
if os.path.isfile(signature_output):
- try:
- i = sys.argv.index('--overwrite-signature')
- del sys.argv[i]
- except ValueError:
+ overwrite = get_option(sys_argv, '--overwrite-signature', False)
+ if not overwrite:
print >> sys.stderr, 'Signature file %r exists. Use --overwrite-signature to overwrite.' % (signature_output)
sys.exit()
+ modulename = get_option_value(sys_argv,'-m',os.path.basename(name),os.path.basename(name))
output_stream = open(signature_output,'w')
flag = 'file'
- file_names = []
+ file_names = []
only_names = []
skip_names = []
options = []
- for word in sys.argv[1:]:
+ for word in sys_argv[1:]:
if word=='': pass
elif word=='only:': flag = 'only'
elif word=='skip:': flag = 'skip'
@@ -99,15 +140,22 @@
else:
{'file': file_names,'only': only_names, 'skip': skip_names}[flag].append(word)
+ if options:
+ sys.stderr.write('Unused options: %s\n' % (', '.join(options)))
+
output_stream.write('''! -*- f90 -*-
! Note: the context of this file is case sensitive.
''')
output_stream.write('PYTHON MODULE %s\n' % (module_name))
output_stream.write(' INTERFACE\n\n')
for filename in file_names:
+ if not os.path.isfile(filename):
+ sys.stderr.write('No or not a file %r. Skipping.\n' % (filename))
+ continue
+ sys.stderr.write('Parsing %r..\n' % (filename))
block = parse(filename)
- output_stream.write('! File: %s, source mode = %s\n' % (filename, block.reader.mode))
- if isinstance(block.content[0],PythonModule):
+ output_stream.write('! File: %s, source mode = %r\n' % (filename, block.reader.mode))
+ if block.content and isinstance(block.content[0],PythonModule):
for subblock in block.content[0].content[0].content:
if isinstance(subblock, EndStatement):
break
@@ -121,23 +169,165 @@
output_stream.close()
return
-def build_extension():
- raise NotImplementedError,'build_extension'
+def build_extension(sys_argv):
+ """
+ Build wrappers to Fortran 90 modules and external subprograms.
+ """
+ modulename = get_option_value(sys_argv,'-m','untitled','unknown')
-def main():
+ build_dir = get_option_value('--build-dir','.',None)
+ if build_dir is None:
+ build_dir = tempfile.mktemp()
+ clean_build_dir = True
+ else:
+ clean_build_dir = False
+ if not os.path.exists(build_dir): os.makedirs(build_dir)
+
+ include_dirs = get_values(sys_argv,'-I',strip_prefix=True)
+ library_dirs = get_values(sys_argv,'-L',strip_prefix=True)
+ libraries = get_values(sys_argv,'-l',strip_prefix=True)
+ _define_macros = get_values(sys_argv,'-D',strip_prefix=True)
+ undef_macros = get_values(sys_argv,'-U',strip_prefix=True)
+ extra_objects = get_values(sys_argv,'','[.](o|a|so|dll|dynlib|sl)')
+
+ define_macros = []
+ for item in _define_macros:
+ name_value = item.split('=',1)
+ if len(name_value)==1:
+ name_value.append(None)
+ if len(name_value)==2:
+ define_macros.append(tuple(name_value))
+ else:
+ print 'Invalid use of -D:',name_value
+
+ pyf_files = get_values(sys_argv,'','[.]pyf')
+ fortran_files = get_values(sys_argv,'','[.](f|f90|F90|F)')
+ c_files = get_values(sys_argv,'','[.](c|cpp|C|CPP|c[+][+])')
+
+ fc_flags = get_values(sys_argv,'--fcompiler=')
+
+ options = get_values(sys_argv,'-')
+ if options:
+ sys.stderr.write('Unused options: %s\n' % (', '.join(options)))
+
+ if pyf_files:
+ parse_files = pyf_files
+ else:
+ parse_files = fortran_files + c_files
+
+ f90_modules = []
+ external_subprograms = []
+
+ for filename in parse_files:
+ if not os.path.isfile(filename):
+ sys.stderr.write('No or not a file %r. Skipping.\n' % (filename))
+ continue
+ sys.stderr.write('Parsing %r..\n' % (filename))
+ for block in parse(filename, include_dirs=include_dirs).content:
+ if isinstance(block, Module):
+ f90_modules.append(block)
+ elif isinstance(block, (Subroutine, Function)):
+ external_subprograms.append(block)
+ else:
+ sys.stderr.write("Unhandled structure: %r\n" % (block.__class__))
+
+ from py_wrap import PythonWrapperModule
+ def configuration(parent_package='', top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('',parent_package,top_path)
+ flibname = modulename + '_fortran_f2py'
+ if fortran_files:
+ config.add_library(flibname,
+ sources = fortran_files)
+ libraries.insert(0,flibname)
+
+ for block in f90_modules:
+ wrapper = PythonWrapperModule(block.name)
+ wrapper.add(block)
+ c_code = wrapper.c_code()
+ f_code = wrapper.fortran_code()
+ c_fn = os.path.join(build_dir,'%smodule.c' % (block.name))
+ f_fn = os.path.join(build_dir,'%s_f_wrappers_f2py.f' % (block.name))
+ f = open(c_fn,'w')
+ f.write(c_code)
+ f.close()
+ f = open(f_fn,'w')
+ f.write(f_code)
+ f.close()
+ f_lib = '%s_f_wrappers_f2py' % (block.name)
+ config.add_library(f_lib,
+ sources = [f_fn])
+ config.add_extension(block.name,
+ sources=[c_fn] + c_files,
+ libraries = [f_lib] + libraries,
+ define_macros = define_macros,
+ undef_macros = undef_macros,
+ include_dirs = include_dirs,
+ extra_objects = extra_objects,
+ )
+ if external_subprograms:
+ wrapper = PythonWrapper(modulename)
+ for block in external_subprograms:
+ wrapper.add(block)
+ c_code = wrapper.c_code()
+ f_code = wrapper.fortran_code()
+ c_fn = os.path.join(temp_dir,'%smodule.c' % (modulename))
+ f_fn = os.path.join(temp_dir,'%s_f_wrappers_f2py.f' % (modulename))
+ f = open(c_fn,'w')
+ f.write(c_code)
+ f.close()
+ f = open(f_fn,'w')
+ f.write(f_code)
+ f.close()
+ f_lib = '%s_f_wrappers_f2py' % (modulename)
+ config.add_library(f_lib,
+ sources = [f_fn])
+ config.add_extension(modulename,
+ sources=[c_fn] + c_files,
+ libraries = [f_lib] + libraries,
+ define_macros = define_macros,
+ undef_macros = undef_macros,
+ include_dirs = include_dirs,
+ extra_objects = extra_objects,
+ )
+ return config
+
+ old_sys_argv = sys.argv[:]
+ new_sys_argv = [sys.argv[0]] + ['build',
+ '--build-temp',build_dir,
+ '--build-base',build_dir,
+ '--build-platlib','.']
+ if fc_flags:
+ new_sys_argv += ['config_fc'] + fc_flags
+ sys.argv[:] = new_sys_argv
+
+ sys.stderr.write('setup arguments: %r' % (' '.join(sys.argv)))
+
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
+
+ sys.argv[:] = old_sys_argv
+
+ if clean_build_dir and os.path.exists(build_dir):
+ sys.stderr.write('Removing build directory %s\n'%(build_dir))
+ shutil.rmtree(build_dir)
+ return
+
+def main(sys_argv = None):
""" Main function of f2py script.
"""
- if '--help-link' in sys.argv[1:]:
- sys.argv.remove('--help-link')
+ if sys_argv is None:
+ sys_argv = sys.argv[1:]
+ if '--help-link' in sys_argv:
+ sys_argv.remove('--help-link')
from numpy.distutils.system_info import show_all
show_all()
return
- if '-c' in sys.argv[1:]:
- i = sys.argv.index('-c')
- del sys.argv[i]
- build_extension()
+ if '-c' in sys_argv:
+ sys_argv.remove('-c')
+ build_extension(sys_argv)
return
- if '-h' in sys.argv[1:]:
- dump_signature()
+ if '-h' in sys_argv:
+ dump_signature(sys_argv)
return
print >> sys.stdout, __usage__
Modified: trunk/numpy/f2py/lib/parser/api.py
===================================================================
--- trunk/numpy/f2py/lib/parser/api.py 2006-10-03 15:52:44 UTC (rev 3249)
+++ trunk/numpy/f2py/lib/parser/api.py 2006-10-04 09:49:54 UTC (rev 3250)
@@ -30,9 +30,24 @@
and the directory of file name.
"""
import os
+ import re
from readfortran import FortranFileReader, FortranStringReader
from parsefortran import FortranParser
if os.path.isfile(input):
+ name,ext = os.path.splitext(input)
+ if ext.lower() in ['.c']:
+ # get signatures from C file comments starting with `/*f2py` and ending with `*/`.
+ # TODO: improve parser to take line number offset making line numbers in
+ # parser messages correct.
+ f2py_c_comments = re.compile('/[*]\s*f2py\s.*[*]/',re.I | re.M)
+ f = open(filename,'r')
+ c_input = ''
+ for s1 in f2py_c_comments.findall(f.read()):
+ c_input += s1[2:-2].lstrip()[4:] + '\n'
+ f.close()
+ if isfree is None: isfree = True
+ if isstrict is None: isstrict = True
+ return parse(c_input, isfree, isstrict, include_dirs)
reader = FortranFileReader(input,
include_dirs = include_dirs)
if isfree is None: isfree = reader.isfree
Modified: trunk/numpy/f2py/lib/parser/base_classes.py
===================================================================
--- trunk/numpy/f2py/lib/parser/base_classes.py 2006-10-03 15:52:44 UTC (rev 3249)
+++ trunk/numpy/f2py/lib/parser/base_classes.py 2006-10-04 09:49:54 UTC (rev 3250)
@@ -122,6 +122,14 @@
self.init = None
return
+ def __repr__(self):
+ l = []
+ for a in ['name','typedecl','dimension','bounds','length','attributes','intent','bind','check','init']:
+ v = getattr(self,a)
+ if v:
+ l.append('%s=%r' % (a,v))
+ return 'Variable: ' + ', '.join(l)
+
def get_bit_size(self):
typesize = self.typedecl.get_bit_size()
if self.is_pointer():
@@ -372,7 +380,7 @@
attr = getattr(self, n, None)
if not attr: continue
if hasattr(attr, 'torepr'):
- r = attr.torepr(depht-1,incrtab)
+ r = attr.torepr(depth-1,incrtab)
else:
r = repr(attr)
l.append(ttab + '%s=%s' % (n, r))
Modified: trunk/numpy/f2py/lib/parser/block_statements.py
===================================================================
--- trunk/numpy/f2py/lib/parser/block_statements.py 2006-10-03 15:52:44 UTC (rev 3249)
+++ trunk/numpy/f2py/lib/parser/block_statements.py 2006-10-04 09:49:54 UTC (rev 3250)
@@ -34,7 +34,7 @@
def get_type_by_name(self, name):
implicit_rules = self.a.implicit_rules
if implicit_rules is None:
- raise AnalyzeError,'Implicit rules mapping is null'
+ raise AnalyzeError,'Implicit rules mapping is null while getting %r type' % (name)
l = name[0].lower()
if implicit_rules.has_key(l):
return implicit_rules[l]
@@ -86,8 +86,9 @@
return stmt
return
- def topyf(self):
- pass
+ def topyf(self, tab=' '):
+ sys.stderr.write('HasUseStmt.topyf not implemented\n')
+ return ''
class HasVariables:
@@ -160,7 +161,7 @@
if isinstance(known_attributes,(list, tuple)):
if uattr not in known_attributes:
self.warning('unknown attribute %r' % (attr))
- elif known_attributes(uattr):
+ elif not known_attributes(uattr):
self.warning('unknown attribute %r' % (attr))
attributes.append(uattr)
return
@@ -266,6 +267,7 @@
module_provides = {}, # all symbols that are public and so
# can be imported via USE statement
# by other blocks
+ module_interface = {}
)
known_attributes = ['PUBLIC', 'PRIVATE']
@@ -281,6 +283,9 @@
def get_provides(self):
return self.a.module_provides
+ def get_interface(self):
+ return self.a.module_interface
+
def analyze(self):
content = self.content[:]
@@ -310,9 +315,11 @@
def topyf(self, tab=''):
s = tab + 'MODULE '+self.name + '\n'
s += HasImplicitStmt.topyf(self, tab=tab+' ')
- s += HasAttributesStmt.topyf(self, tab=tab+' ')
+ s += HasAttributes.topyf(self, tab=tab+' ')
s += HasTypeDecls.topyf(self, tab=tab+' ')
s += HasVariables.topyf(self, tab=tab+' ')
+ for name, stmt in self.a.module_interface.items():
+ s += stmt.topyf(tab=tab+' ')
s += tab + ' CONTAINS\n'
for name, stmt in self.a.module_subprogram.items():
s += stmt.topyf(tab=tab+' ')
@@ -400,7 +407,7 @@
blocktype = 'interface'
class Interface(BeginStatement, HasImplicitStmt, HasUseStmt,
- HasModuleProcedures
+ HasModuleProcedures, HasAttributes
):
"""
INTERFACE [<generic-spec>] | ABSTRACT INTERFACE
@@ -423,6 +430,8 @@
a = AttributeHolder(interface_provides = {})
+ known_attributes = ['PUBLIC','PRIVATE']
+
def get_classes(self):
l = intrinsic_type_spec + interface_specification
if self.reader.mode=='pyf':
@@ -455,22 +464,36 @@
if isinstance(stmt, self.end_stmt_cls):
break
stmt.analyze()
- assert isinstance(stmt, SubProgramStatement),`stmt.__class__.__name__`
+ #assert isinstance(stmt, SubProgramStatement),`stmt.__class__.__name__`
if content:
self.show_message('Not analyzed content: %s' % content)
- parent_provides = self.parent.get_provides()
- if parent_provides is not None:
- if self.is_public():
- if parent_provides.has_key(self.name):
- self.warning('interface name conflict with %s, overriding.' % (self.name))
- parent_provides[self.name] = self
-
+ if self.parent.a.variables.has_key(self.name):
+ var = self.parent.a.variables.pop(self.name)
+ self.update_attributes(var.attributes)
+
+ parent_interface = self.parent.get_interface()
+ if parent_interface.has_key(self.name):
+ p = parent_interface[self.name]
+ last = p.content.pop()
+ assert isinstance(last,EndInterface),`last.__class__`
+ p.content += self.content
+ p.update_attributes(self.a.attributes)
+ else:
+ parent_interface[self.name] = self
return
def is_public(self):
- return True # TODO: need review.
+ return 'PUBLIC' in self.a.attributes
+ def topyf(self, tab=''):
+ s = tab + self.tostr() + '\n'
+ s += HasImplicitStmt.topyf(self, tab=tab+' ')
+ s += HasAttributes.topyf(self, tab=tab+' ')
+ s += HasUseStmt.topyf(self, tab=tab+' ')
+ s += tab + 'END' + self.tostr() + '\n'
+ return s
+
# Subroutine
class SubProgramStatement(BeginStatement, ProgramBlock,
@@ -927,7 +950,7 @@
component_names = [], # specifies component order for sequence types
components = {}
)
- known_attributes = re.compile(r'\A(PUBLIC|PRIVATE|SEQUENCE|ABSTRACT|BIND\s*\(.*\))\Z').match
+ known_attributes = re.compile(r'\A(PUBLIC|PRIVATE|SEQUENCE|ABSTRACT|BIND\s*\(.*\))\Z',re.I).match
def process_item(self):
line = self.item.get_line()[4:].lstrip()
Modified: trunk/numpy/f2py/lib/parser/parsefortran.py
===================================================================
--- trunk/numpy/f2py/lib/parser/parsefortran.py 2006-10-03 15:52:44 UTC (rev 3249)
+++ trunk/numpy/f2py/lib/parser/parsefortran.py 2006-10-04 09:49:54 UTC (rev 3250)
@@ -66,10 +66,10 @@
message = reader.format_message('FATAL ERROR',
'while processing line',
reader.linecount, reader.linecount)
- reader.show_message(message, sys.stdout)
+ reader.show_message(message, sys.stderr)
reader = reader.reader
- traceback.print_exc(file=sys.stdout)
- self.reader.show_message(red_text('STOPPED PARSING'), sys.stdout)
+ traceback.print_exc(file=sys.stderr)
+ self.reader.show_message(red_text('STOPPED PARSING'), sys.stderr)
return
return
@@ -84,8 +84,12 @@
self.block.analyze()
except AnalyzeError:
pass
- except:
- raise
+ except Exception, msg:
+ if str(msg) != '123454321':
+ traceback.print_exc(file=sys.stderr)
+ self.reader.show_message(red_text('FATAL ERROR: STOPPED ANALYSING %r CONTENT' % (self.reader.source) ), sys.stderr)
+ sys.exit(123454321)
+ return
self.is_analyzed = True
return
Modified: trunk/numpy/f2py/lib/parser/statements.py
===================================================================
--- trunk/numpy/f2py/lib/parser/statements.py 2006-10-03 15:52:44 UTC (rev 3249)
+++ trunk/numpy/f2py/lib/parser/statements.py 2006-10-04 09:49:54 UTC (rev 3250)
@@ -900,8 +900,8 @@
module = modules[self.name]
use_provides = self.parent.a.use_provides
+ print use
-
return
class Exit(Statement):
Added: trunk/numpy/f2py/lib/py_wrap.py
===================================================================
--- trunk/numpy/f2py/lib/py_wrap.py 2006-10-03 15:52:44 UTC (rev 3249)
+++ trunk/numpy/f2py/lib/py_wrap.py 2006-10-04 09:49:54 UTC (rev 3250)
@@ -0,0 +1,410 @@
+__all__ = ['PythonWrapperModule']
+
+import re
+import os
+import sys
+
+from parser.api import *
+from wrapper_base import *
+
+class PythonWrapperModule(WrapperBase):
+
+ main_template = '''\
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+#include "Python.h"
+
+#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API
+#include "numpy/arrayobject.h"
+#include "numpy/arrayscalars.h"
+
+%(header_list)s
+
+%(typedef_list)s
+
+%(extern_list)s
+
+%(c_code_list)s
+
+%(capi_code_list)s
+
+%(objdecl_list)s
+
+static PyObject *f2py_module;
+
+static PyMethodDef f2py_module_methods[] = {
+ %(module_method_list)s
+ {NULL,NULL,0,NULL}
+};
+
+PyMODINIT_FUNC init%(modulename)s(void) {
+ f2py_module = Py_InitModule("%(modulename)s", f2py_module_methods);
+ import_array();
+ %(module_init_list)s
+ if (PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ImportError, "can\'t initialize module %(modulename)s");
+ return;
+ }
+}
+#ifdef __cplusplus
+}
+#endif
+'''
+
+ main_fortran_template = '''\
+! -*- f90 -*-
+%(fortran_code_list)s
+'''
+ def __init__(self, modulename):
+ WrapperBase.__init__(self)
+ self.modulename = modulename
+
+ self.header_list = []
+ self.typedef_list = []
+ self.extern_list = []
+ self.objdecl_list = []
+ self.c_code_list = []
+ self.capi_code_list = []
+
+ self.module_method_list = []
+ self.module_init_list = []
+
+ self.fortran_code_list = []
+
+ self.list_names = ['header', 'typedef', 'extern', 'objdecl',
+ 'c_code','capi_code','module_method','module_init',
+ 'fortran_code']
+
+ return
+
+ def add(self, block):
+ if isinstance(block, BeginSource):
+ for name, moduleblock in block.a.module.items():
+ self.add(moduleblock)
+ #for name, subblock in block.a.external_subprogram.items():
+ # self.add(subblock)
+ elif isinstance(block, (Subroutine, Function)):
+ self.info('Generating interface for %s' % (block.name))
+ f = PythonCAPIFunction(self, block)
+ f.fill()
+ elif isinstance(block, Module):
+ for name,declblock in block.a.type_decls.items():
+ self.add(declblock)
+ elif isinstance(block, TypeDecl):
+ self.info('Generating interface for %s' % (block.name))
+ PythonCAPIDerivedType(self, block)
+ elif isinstance(block, tuple(declaration_type_spec)):
+ self.info('Generating interface for %s' % (block.name))
+ PythonCAPIIntrinsicType(self, block)
+ else:
+ raise NotImplementedError,`block.__class__.__name__`
+ return
+
+ def c_code(self):
+ return self.apply_attributes(self.main_template)
+ def fortran_code(self):
+ return self.apply_attributes(self.main_fortran_template)
+
+class PythonCAPIIntrinsicType(WrapperBase):
+ """
+ Fortran intrinsic type hooks.
+ """
+ _defined_types = []
+ def __init__(self, parent, typedecl):
+ WrapperBase.__init__(self)
+ self.name = name = typedecl.name
+ if name in self._defined_types:
+ return
+ self._defined_types.append(name)
+
+ self.ctype = ctype = typedecl.get_c_type()
+
+ if ctype.startswith('npy_'):
+ WrapperCCode(parent, 'pyobj_from_%s' % (ctype))
+ return
+
+ if not ctype.startswith('f2py_type_'):
+ raise NotImplementedError,`name,ctype`
+
+ for n in parent.list_names:
+ l = getattr(parent,n + '_list')
+ l.append(self.apply_attributes(getattr(self, n+'_template','')))
+
+ return
+
+class PythonCAPIDerivedType(WrapperBase):
+ """
+ Fortran 90 derived type hooks.
+ """
+
+ header_template = '''\
+#define %(oname)sObject_Check(obj) \\
+ PyObject_TypeCheck((PyObject*)obj, &%(oname)sType)
+#define %(init_func)s_f \\
+ F_FUNC(%(init_func)s,%(INIT_FUNC)s)
+'''
+
+ typedef_template = '''\
+typedef void * %(ctype)s;
+typedef struct {
+ PyObject_HEAD
+ %(ptrstruct_list)s
+ %(ctype)s data;
+} %(oname)sObject;
+'''
+
+ extern_template = '''\
+static PyTypeObject %(oname)sType;
+'''
+
+ objdecl_template = '''\
+static PyMethodDef %(oname)s_methods[] = {
+ %(type_method_list)s
+ {NULL} /* Sentinel */
+};
+
+static PyGetSetDef %(oname)s_getseters[] = {
+ %(type_getseters_list)s
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject %(oname)sType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "%(name)s", /*tp_name*/
+ sizeof(%(oname)sObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)%(oname)s_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ %(oname)s_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ "Fortran derived type %(name)s objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ %(oname)s_methods, /* tp_methods */
+ 0 /*%(oname)s_members*/, /* tp_members */
+ %(oname)s_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)%(oname)s_init, /* tp_init */
+ 0, /* tp_alloc */
+ %(oname)s_new, /* tp_new */
+};
+'''
+
+ module_init_template = '''\
+if (PyType_Ready(&%(oname)sType) < 0)
+ return;
+PyModule_AddObject(f2py_module, "%(name)s",
+ (PyObject *)&%(oname)sType);
+'''
+
+ c_code_template = '''\
+static void %(init_func)s_c(
+ %(init_func_c_arg_clist)s) {
+ %(init_func_c_body_list)s
+}
+'''
+
+ capi_code_template = '''\
+static void %(oname)s_dealloc(%(oname)sObject* self) {
+ if (self->data)
+ PyMem_Free(self->data);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+static int pyobj_to_%(ctype)s(PyObject *obj,
+ %(ctype)s* value_ptr) {
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+ if (%(oname)sObject_Check(obj)) {
+ if (!memcpy(value_ptr,((%(oname)sObject *)obj)->data, %(byte_size)s)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "failed to copy %(name)s instance memory to %(ctype)s object.");
+ } else {
+ return_value = 1;
+ }
+ }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s: return_value=%%d, PyErr_Occurred()=%%p\\n", return_value, PyErr_Occurred());
+#endif
+ return return_value;
+}
+
+static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value_ptr) {
+ %(oname)sObject* obj = (%(oname)sObject*)(%(oname)sType.tp_alloc(&%(oname)sType, 0));
+ if (obj == NULL)
+ return NULL;
+ obj->data = PyMem_Malloc(%(byte_size)s);
+ if (obj->data == NULL) {
+ Py_DECREF(obj);
+ return PyErr_NoMemory();
+ }
+ if (value_ptr) {
+ if (!memcpy(obj->data, value_ptr, %(byte_size)s)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "failed to copy %(ctype)s object memory to %(name)s instance.");
+ }
+ }
+ %(init_func)s_f(%(init_func)s_c, obj, obj->data);
+ return (PyObject*)obj;
+}
+
+static PyObject * %(oname)s_new(PyTypeObject *type,
+ PyObject *args, PyObject *kwds)
+{
+ return pyobj_from_%(ctype)s(NULL);
+}
+
+static int %(oname)s_init(%(oname)sObject *self,
+ PyObject *capi_args, PyObject *capi_kwds)
+{
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"%(oname)s_init()\\n");
+#endif
+ if (!PyArg_ParseTuple(capi_args,"%(attr_format_elist)s"
+ %(attr_init_clist)s))
+ return_value = -1;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"%(oname)s_init: return_value=%%d, PyErr_Occurred()=%%p\\n", return_value, PyErr_Occurred());
+#endif
+ return return_value;
+}
+
+static PyObject * %(oname)s_as_tuple(%(oname)sObject * self) {
+ return Py_BuildValue("%(as_tuple_format_elist)s"
+ %(as_tuple_arg_clist)s);
+}
+
+static PyObject * %(oname)s_repr(PyObject * self) {
+ PyObject* r = PyString_FromString("%(name)s(");
+ PyString_ConcatAndDel(&r, PyObject_Repr(%(oname)s_as_tuple((%(oname)sObject*)self)));
+ PyString_ConcatAndDel(&r, PyString_FromString(")"));
+ return r;
+}
+
+%(getset_func_list)s
+'''
+
+ fortran_code_template = '''\
+ subroutine %(init_func)s(init_func_c, self, obj)
+ %(use_stmt_list)s
+ external init_func_c
+! self is %(oname)sObject
+ external self
+ %(ftype)s obj
+ call init_func_c(%(init_func_f_arg_clist)s)
+ end
+'''
+
+ #module_method_template = ''''''
+
+ _defined_types = []
+ def __init__(self, parent, typedecl):
+ WrapperBase.__init__(self)
+ name = typedecl.name
+ if name in self._defined_types:
+ return
+ self._defined_types.append(name)
+
+ self.name = name
+ self.oname = oname = 'f2py_' + name
+ self.ctype = typedecl.get_c_type()
+ self.ctype_ptrs = self.ctype + '_ptrs'
+ self.ftype = typedecl.get_f_type()
+ self.byte_size = byte_size = typedecl.get_bit_size() / CHAR_BIT
+ WrapperCPPMacro(parent, 'F_FUNC')
+
+ self.init_func_f_arg_list = ['self']
+ self.init_func_c_arg_list = ['%sObject *self' % (self.oname)]
+ self.init_func_c_body_list = []
+ self.ptrstruct_list = []
+ self.attr_decl_list = []
+ self.attr_format_list = []
+ self.attr_init_list = []
+ self.as_tuple_format_list = []
+ self.as_tuple_arg_list = []
+ self.getset_func_list = []
+ self.type_getseters_list = []
+ for n in typedecl.a.component_names:
+ v = typedecl.a.components[n]
+ t = v.get_typedecl()
+ ct = t.get_c_type()
+ on = 'f2py_' + t.name
+ parent.add(t)
+ self.ptrstruct_list.append('%s* %s_ptr;' % (ct, n))
+ self.init_func_f_arg_list.append('obj %% %s' % (n))
+ self.init_func_c_arg_list.append('\n%s * %s_ptr' % (ct, n))
+ self.init_func_c_body_list.append('''\
+if (!((void*)%(n)s_ptr >= self->data
+ && (void*)%(n)s_ptr < self->data + %(byte_size)s ))
+ fprintf(stderr,"INCONSISTENCY IN %(name)s WRAPPER: "
+ "self->data=%%p <= %(n)s_ptr=%%p < self->data+%(byte_size)s=%%p\\n",
+ self->data, %(n)s_ptr, self->data + %(byte_size)s);
+self->%(n)s_ptr = %(n)s_ptr;
+''' % (locals()))
+ self.attr_format_list.append('O&')
+ WrapperCCode(parent, 'pyobj_to_%s' % (ct))
+ self.attr_init_list.append('\npyobj_to_%s, self->%s_ptr' % (ct,n))
+ WrapperCCode(parent, 'pyobj_from_%s' % (ct))
+ self.as_tuple_format_list.append('O&')
+ self.as_tuple_arg_list.append('\npyobj_from_%s, self->%s_ptr' % (ct, n))
+ self.getset_func_list.append('''\
+static PyObject * %(oname)s_get_%(n)s(%(oname)sObject *self,
+ void *closure) {
+ return pyobj_from_%(ct)s(self->%(n)s_ptr);
+}
+static int %(oname)s_set_%(n)s(%(oname)sObject *self,
+ PyObject *value, void *closure)
+{
+ if (value == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "Cannot delete %(name)s attribute %(n)s");
+ return -1;
+ }
+ if (pyobj_to_%(ct)s(value, self->%(n)s_ptr))
+ return 0;
+ return -1;
+}
+''' % (locals()))
+ self.type_getseters_list.append('{"%(n)s",(getter)%(oname)s_get_%(n)s, (setter)%(oname)s_set_%(n)s,\n "component %(n)s",NULL},' % (locals()))
+ if self.attr_init_list: self.attr_init_list.insert(0,'')
+ if self.as_tuple_arg_list: self.as_tuple_arg_list.insert(0,'')
+ self.init_func = self.ctype + '_init'
+ self.INIT_FUNC = self.init_func.upper()
+
+ self.type_method_list = []
+ self.type_method_list.append('{"as_tuple",(PyCFunction)%(oname)s_as_tuple,METH_NOARGS,\n "Return %(name)s components as tuple."},' % (self.__dict__))
+ self.cname = typedecl.get_c_name()
+
+ self.use_stmt_list = []
+ if isinstance(typedecl.parent, Module):
+ self.use_stmt_list.append('use %s' % (typedecl.parent.name))
+
+ for n in parent.list_names:
+ l = getattr(parent,n + '_list')
+ l.append(self.apply_attributes(getattr(self, n+'_template','')))
+ return
Modified: trunk/numpy/f2py/lib/python_wrapper.py
===================================================================
--- trunk/numpy/f2py/lib/python_wrapper.py 2006-10-03 15:52:44 UTC (rev 3249)
+++ trunk/numpy/f2py/lib/python_wrapper.py 2006-10-04 09:49:54 UTC (rev 3250)
@@ -7,10 +7,6 @@
from parser.api import *
-#from block_statements import *
-#from typedecl_statements import intrinsic_type_spec, Character
-#from utils import CHAR_BIT
-
from wrapper_base import *
class PythonWrapperModule(WrapperBase):
@@ -65,8 +61,6 @@
def __init__(self, modulename):
WrapperBase.__init__(self)
self.modulename = modulename
- #self.include_list = []
- #self.cppmacro_list = []
self.header_list = []
self.typedef_list = []
@@ -80,11 +74,6 @@
self.fortran_code_list = []
- #self.defined_types = []
- #self.defined_macros = []
- #self.defined_c_functions = []
- #self.defined_typedefs = []
-
self.list_names = ['header', 'typedef', 'extern', 'objdecl',
'c_code','capi_code','module_method','module_init',
'fortran_code']
More information about the Numpy-svn
mailing list