Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 45 additions & 25 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,71 @@ list(APPEND tests
arrays
arrays_fixed
arrays_in_derived_types_issue50
auto_raise_error
class_names
cylinder
decoded_strings
default_i8
derived-type-aliases
derivedtypes
derivedtypes_procedure
docstring
dump_package
elemental
errorbinding
example2
extends
fixed_1D_derived_type_array_argument
fortran_oo
intent_out_size
interface
issue105_function_definition_with_empty_lines
issue206_subroutine_oldstyle
issue227_allocatable
issue235_allocatable_classes
issue254_getter
issue258_derived_type_attributes
issue261_array_shapes
issue297_ignored_abstract_classes
issue301_complex_types
issue302_pointer_warning
issue305_multiple_abstract_interfaces
issue307_logical_array
issue32
keep_single_interface
keyword_renaming_issue160
kind_map_default
long_subroutine_name
method_optional
mockderivetype
mod_arg_clash
name_collision
optional_args_issue53
optional_derived_arrays
optional_string
output_kind
passbyreference
recursive_type_array
relative_import
remove_pointer_arg
return_array
return_bool
signature_vs_backend
string_array_input_f2py
strings
subroutine_args
subroutine_contains_issue101
type_bn
kind_map_default
docstring
return_array
intent_out_size
string_array_input_f2py
type_check
optional_string
long_subroutine_name
output_kind
remove_pointer_arg
fortran_oo
issue254_getter
issue258_derived_type_attributes
issue206_subroutine_oldstyle
issue227_allocatable
issue235_allocatable_classes
issue297_ignored_abstract_classes
issue305_multiple_abstract_interfaces
auto_raise_error
dump_package
method_optional
relative_import
decoded_strings
keep_single_interface
return_bool
issue307_logical_array
)

# TODO: Fix these failing examples
# callback_print_function_issue93 # undefined symbol: pyfunc_print_
# f2py_string_input # undefined symbol: string_in_array_ (linking issue)
# issue41_abstract_classes # AttributeError: 'myclass_t' object has no attribute 'get_value'
# issue299_directc_nested_functions# types.py shadows stdlib types module
# recursive_type # Error: Derived type 'node' at (1) has not been declared

foreach(test ${tests})
message(STATUS "Adding test ${test}")
add_test(
Expand Down
119 changes: 68 additions & 51 deletions examples/Makefile
Original file line number Diff line number Diff line change
@@ -1,56 +1,73 @@
include make.inc

EXAMPLES = arrayderivedtypes \
arrays \
arrays_fixed \
arrays_in_derived_types_issue50 \
class_names \
cylinder \
derivedtypes \
elemental \
example2 \
extends \
interface \
issue105_function_definition_with_empty_lines \
issue32 \
keyword_renaming_issue160 \
mockderivetype \
mod_arg_clash \
name_collision \
optional_args_issue53 \
optional_derived_arrays \
passbyreference \
strings \
subroutine_contains_issue101 \
type_bn \
docstring \
type_check \
derivedtypes_procedure \
return_array \
string_array_input_f2py \
optional_string \
long_subroutine_name \
kind_map_default \
intent_out_size \
output_kind \
remove_pointer_arg \
fortran_oo \
issue254_getter \
issue258_derived_type_attributes \
issue206_subroutine_oldstyle \
issue227_allocatable \
issue235_allocatable_classes \
issue297_ignored_abstract_classes \
issue305_multiple_abstract_interfaces \
issue306_allocatable_realloc \
auto_raise_error \
dump_package \
method_optional \
relative_import \
decoded_strings \
keep_single_interface \
return_bool \
issue307_logical_array
EXAMPLES = \
arrayderivedtypes \
arrays \
arrays_fixed \
arrays_in_derived_types_issue50 \
auto_raise_error \
class_names \
cylinder \
decoded_strings \
default_i8 \
derived-type-aliases \
derivedtypes \
derivedtypes_procedure \
docstring \
dump_package \
elemental \
errorbinding \
example2 \
extends \
fixed_1D_derived_type_array_argument \
fortran_oo \
intent_out_size \
interface \
issue105_function_definition_with_empty_lines \
issue206_subroutine_oldstyle \
issue227_allocatable \
issue235_allocatable_classes \
issue254_getter \
issue258_derived_type_attributes \
issue261_array_shapes \
issue297_ignored_abstract_classes \
issue301_complex_types \
issue302_pointer_warning \
issue305_multiple_abstract_interfaces \
issue307_logical_array \
issue32 \
keep_single_interface \
keyword_renaming_issue160 \
kind_map_default \
long_subroutine_name \
method_optional \
mockderivetype \
mod_arg_clash \
name_collision \
optional_args_issue53 \
optional_derived_arrays \
optional_string \
output_kind \
passbyreference \
recursive_type_array \
relative_import \
remove_pointer_arg \
return_array \
return_bool \
signature_vs_backend \
string_array_input_f2py \
strings \
subroutine_args \
subroutine_contains_issue101 \
type_bn \
type_check

# TODO: Fix these failing examples
# callback_print_function_issue93 \ # undefined symbol: pyfunc_print_
# f2py_string_input \ # undefined symbol: string_in_array_ (linking issue)
# issue41_abstract_classes \ # AttributeError: 'myclass_t' object has no attribute 'get_value'
# issue299_directc_nested_functions \# types.py shadows stdlib types module
# recursive_type \ # Error: Derived type 'node' at (1) has not been declared

DIRECTC ?= no

Expand Down
15 changes: 15 additions & 0 deletions examples/errorbinding/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python
"""Minimal test for errorbinding example - verifies the module can be imported and used."""

import ExampleDerivedTypes

# Create a type with procedure
obj = ExampleDerivedTypes.Datatypes.typewithprocedure()

# Call init method
obj.init(a=1.0, n=5)

# Call info method (writes to stdout)
obj.info(lun=6)

print("OK: errorbinding test passed")
15 changes: 15 additions & 0 deletions examples/errorbinding/tests_pkg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python
"""Minimal test for errorbinding example (package mode) - verifies the module can be imported and used."""

import ExampleDerivedTypes_pkg

# Create a type with procedure
obj = ExampleDerivedTypes_pkg.datatypes.typewithprocedure()

# Call init method
obj.init(a=1.0, n=5)

# Call info method (writes to stdout)
obj.info(lun=6)

print("OK: errorbinding package test passed")
3 changes: 2 additions & 1 deletion examples/fixed_1D_derived_type_array_argument/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ wrap :
python :
f2py-f90wrap $(F2PYFLAGS) -c -m _test_python f90wrap_functions.f90 *.o
clean :
rm -f *.o *.mod *.so f90wrap* test_python.py build
rm -f *.o *.mod *.so f90wrap* test_python.py
rm -rf build/
21 changes: 16 additions & 5 deletions f90wrap/f90wrapgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,9 @@ def visit_Procedure(self, node):
self.write("subroutine %s%s" % (sub_name, arg_names))
self.indent()
self.write_uses_lines(node)
# Add iso_c_binding when we have derived type arguments (handle arrays use c_int)
if node.transfer_in or node.transfer_out:
self.write("use, intrinsic :: iso_c_binding, only: c_int")
self.write("implicit none")

if node.mod_name is None:
Expand Down Expand Up @@ -881,6 +884,7 @@ def _write_sc_array_wrapper(self, t, el, dims, sizeof_fortran_t):
self.write_type_or_class_lines(t.orig_name)
self.write("integer(c_int), intent(in) :: this(%d)" % sizeof_fortran_t)
self.write("type(%s_ptr_type) :: this_ptr" % t.orig_name)
# Module-level arrays do not need dummy_this declaration (issue #306)

self.write("integer(c_int), intent(out) :: nd")
self.write("integer(c_int), intent(out) :: dtype")
Expand Down Expand Up @@ -1048,6 +1052,8 @@ def _write_array_getset_item(self, t, el, sizeof_fortran_t, getset):
owner_module = self._type_owner(el.type, getattr(t, "mod_name", getattr(t, "name", None)))
self._add_extra_use(extra_uses, owner_module, None)
self.write_uses_lines(el, extra_uses)
# Add iso_c_binding for handle arrays (c_int is immune to -fdefault-integer-8)
self.write("use, intrinsic :: iso_c_binding, only: c_int")
self.write("implicit none")
self.write()

Expand All @@ -1062,15 +1068,15 @@ def _write_array_getset_item(self, t, el, sizeof_fortran_t, getset):
self.write_type_or_class_lines(el.type, same_type, pointer=True)

if this is not None:
self.write("integer, intent(in) :: %s(%d)" % (this, sizeof_fortran_t))
self.write("integer(c_int), intent(in) :: %s(%d)" % (this, sizeof_fortran_t))
if isinstance(t, ft.Type):
self.write("type(%s_ptr_type) :: this_ptr" % t.name)
array_name = self._get_type_member_array_name(t, el.name)
else:
array_name = shorten_long_name("%s_%s" % (t.name, el.name))
self.write("integer, intent(in) :: %s" % (safe_i))
self.write(
"integer, intent(%s) :: %s(%d)"
"integer(c_int), intent(%s) :: %s(%d)"
% (inout, el.name + "item", sizeof_fortran_t)
)
if not same_type:
Expand Down Expand Up @@ -1184,6 +1190,8 @@ def _write_array_len(self, t, el, sizeof_fortran_t):
owner_module = self._type_owner(el.type, getattr(t, "mod_name", getattr(t, "name", None)))
self._add_extra_use(extra_uses, owner_module, None)
self.write_uses_lines(el, extra_uses)
# Add iso_c_binding for handle arrays (c_int is immune to -fdefault-integer-8)
self.write("use, intrinsic :: iso_c_binding, only: c_int")
self.write("implicit none")
self.write()
if "super-type" in t.doc:
Expand All @@ -1196,7 +1204,7 @@ def _write_array_len(self, t, el, sizeof_fortran_t):
self.write_type_or_class_lines(el.type, same_type)
self.write("integer, intent(out) :: %s" % (safe_n))
if this is not None:
self.write("integer, intent(in) :: %s(%d)" % (this, sizeof_fortran_t))
self.write("integer(c_int), intent(in) :: %s(%d)" % (this, sizeof_fortran_t))
if isinstance(t, ft.Type):
self.write("type(%s_ptr_type) :: this_ptr" % t.name)
self.write()
Expand Down Expand Up @@ -1291,6 +1299,9 @@ def _write_scalar_wrapper(self, t, el, sizeof_fortran_t, getset):
self.indent()

self.write_uses_lines(el, extra_uses)
# Add iso_c_binding for handle arrays (c_int is immune to -fdefault-integer-8)
if isinstance(t, ft.Type) or ft.is_derived_type(el.type):
self.write("use, intrinsic :: iso_c_binding, only: c_int")

self.write("implicit none")
if isinstance(t, ft.Type):
Expand All @@ -1300,7 +1311,7 @@ def _write_scalar_wrapper(self, t, el, sizeof_fortran_t, getset):
self.write_type_or_class_lines(el.type, pointer=True)

if isinstance(t, ft.Type):
self.write("integer, intent(in) :: this(%d)" % sizeof_fortran_t)
self.write("integer(c_int), intent(in) :: this(%d)" % sizeof_fortran_t)
self.write("type(%s_ptr_type) :: this_ptr" % t.orig_name)

# Return/set by value
Expand All @@ -1313,7 +1324,7 @@ def _write_scalar_wrapper(self, t, el, sizeof_fortran_t, getset):
if ft.is_derived_type(el.type):
# For derived types elements, treat as opaque reference
self.write(
"integer, intent(%s) :: %s(%d)" % (inout, localvar, sizeof_fortran_t)
"integer(c_int), intent(%s) :: %s(%d)" % (inout, localvar, sizeof_fortran_t)
)

self.write(
Expand Down
2 changes: 1 addition & 1 deletion f90wrap/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ def convert_derived_type_arguments(tree, init_lines, sizeof_fortran_t):
arg.attributes if attr.startswith('intent')]

typename = ft.strip_type(arg.type)
arg.wrapper_type = 'integer'
arg.wrapper_type = 'integer(c_int)'
arg.wrapper_dim = sizeof_fortran_t
sub.types.add(typename)

Expand Down