Fortran to Python interface generator with derived type support for automated wrapper generation
—
Comprehensive type system analysis and utility functions for handling Fortran type conversions, kind mapping, array processing, and interoperability between Fortran and Python type systems.
Functions for analyzing and categorizing Fortran types.
def is_derived_type(typename):
"""
Check if a type name represents a Fortran derived type.
Parameters:
- typename: str, Fortran type name to check
Returns:
bool, True if typename is a derived type
"""
def derived_typename(typename):
"""
Extract the base derived type name from a full type specification.
Parameters:
- typename: str, full Fortran type specification
Returns:
str, base derived type name
"""
def strip_type(t):
"""
Clean and normalize a Fortran type string.
Parameters:
- t: str, Fortran type string to clean
Returns:
str, cleaned type string
"""
def split_type_kind(typename):
"""
Split a Fortran type into base type and kind specification.
Parameters:
- typename: str, Fortran type with possible kind
Returns:
tuple, (base_type, kind) where kind may be None
"""Functions for converting between Fortran, C, and Python type representations.
def f2c_type(typename, kind_map):
"""
Convert Fortran type to equivalent C type.
Parameters:
- typename: str, Fortran type name
- kind_map: dict, mapping of Fortran kinds to C types
Returns:
str, equivalent C type specification
"""
def f2py_type(type, attributes=None):
"""
Get f2py-compatible type specification.
Parameters:
- type: str, Fortran type name
- attributes: list, optional type attributes
Returns:
str, f2py type specification
"""
def normalise_type(typename, kind_map):
"""
Normalize Fortran type name using kind mappings.
Parameters:
- typename: str, Fortran type name to normalize
- kind_map: dict, kind to type mappings
Returns:
str, normalized type name
"""
def fortran_array_type(typename, kind_map):
"""
Get Fortran array type specification for a given base type.
Parameters:
- typename: str, base Fortran type
- kind_map: dict, kind mappings for type resolution
Returns:
str, Fortran array type specification
"""f90wrap recognizes and handles these standard Fortran intrinsic types:
Integer Types:
integer - Default integer typeinteger(kind=int8) - 8-bit signed integerinteger(kind=int16) - 16-bit signed integerinteger(kind=int32) - 32-bit signed integerinteger(kind=int64) - 64-bit signed integerReal Types:
real - Default real type (usually single precision)real(kind=real32) - 32-bit floating pointreal(kind=real64) - 64-bit floating point (double precision)real(kind=real128) - 128-bit floating point (quad precision)Complex Types:
complex - Default complex typecomplex(kind=real32) - Single precision complexcomplex(kind=real64) - Double precision complexCharacter Types:
character - Default character typecharacter(len=*) - Deferred length charactercharacter(len=n) - Fixed length characterLogical Types:
logical - Default logical typelogical(kind=int8) - 8-bit logicalTypes from the iso_c_binding module for C interoperability:
# C integer types
c_int, c_short, c_long, c_long_long
c_signed_char, c_size_t, c_int8_t, c_int16_t, c_int32_t, c_int64_t
# C floating point types
c_float, c_double, c_long_double
# C character types
c_char
# C logical type
c_bool
# C pointer types
c_ptr, c_funptrfrom f90wrap.fortran import is_derived_type, derived_typename, split_type_kind
# Check if type is derived
is_derived = is_derived_type('type(my_type)') # True
is_intrinsic = is_derived_type('integer') # False
# Extract derived type name
base_name = derived_typename('type(my_type)') # 'my_type'
# Split type and kind
base, kind = split_type_kind('real(kind=real64)') # ('real', 'real64')
base, kind = split_type_kind('integer') # ('integer', None)from f90wrap.fortran import f2c_type, f2py_type, normalise_type
# Define kind mappings
kind_map = {
'real64': 'double',
'int32': 'int',
'int64': 'long long'
}
# Convert to C type
c_type = f2c_type('real(kind=real64)', kind_map) # 'double'
c_int = f2c_type('integer(kind=int32)', kind_map) # 'int'
# Get f2py type
f2py_spec = f2py_type('real', ['intent(in)']) # 'real, intent(in)'
# Normalize type
norm_type = normalise_type('real(kind=real64)', kind_map) # 'double'from f90wrap.fortran import fortran_array_type
# Get array type specification
array_type = fortran_array_type('real(kind=real64)', kind_map)
# Returns appropriate array type for the base type# Example kind map for gfortran
gfortran_kinds = {
'real32': 'float',
'real64': 'double',
'int8': 'signed char',
'int16': 'short',
'int32': 'int',
'int64': 'long long'
}
# Example kind map for Intel Fortran
intel_kinds = {
'real32': 'float',
'real64': 'double',
'int8': 'char',
'int16': 'short',
'int32': 'int',
'int64': '__int64' # Intel-specific
}
# Use compiler-specific mappings
def get_kind_map(compiler):
if compiler == 'gfortran':
return gfortran_kinds
elif compiler == 'ifort':
return intel_kinds
else:
return {} # Default mappingsSupport for Fortran 2003 parameterized derived types:
type :: matrix(k, rows, cols)
integer, kind :: k = real64
integer, len :: rows, cols
real(k) :: data(rows, cols)
end typef90wrap handles these by:
Support for object-oriented Fortran features:
type, abstract :: shape
contains
procedure(area_interface), deferred :: area
procedure :: perimeter
end type
type, extends(shape) :: circle
real :: radius
contains
procedure :: area => circle_area
end typef90wrap provides:
Handling of Fortran generic interfaces:
interface operator(+)
module procedure add_reals, add_integers
end interfacef90wrap creates:
The type system includes validation to catch common errors:
Comprehensive error reporting for type issues:
# Example error messages
TypeError: "Unsupported Fortran type: 'type(unsupported_type)'"
ValueError: "Invalid kind specification: 'real(kind=invalid_kind)'"
RuntimeError: "Circular dependency detected in type hierarchy"Install with Tessl CLI
npx tessl i tessl/pypi-f90wrap