-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreation_wrapper.f90
More file actions
110 lines (84 loc) · 4.03 KB
/
creation_wrapper.f90
File metadata and controls
110 lines (84 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
!> Wrapper for interfacing `m_error_v_creation` with Python
!>
!> Written by hand here.
!> Generation to be automated in future (including docstrings of some sort).
module m_error_v_creation_w
! => allows us to rename on import to avoid clashes
! "o_" for original (TODO: better naming convention)
use m_error_v_creation, only: &
o_create_error => create_error, &
o_create_errors => create_errors
use m_error_v, only: ErrorV
! The manager module, which makes this all work
use m_error_v_manager, only: &
error_v_manager_get_available_instance_index => get_available_instance_index, &
error_v_manager_set_instance_index_to => set_instance_index_to, &
error_v_manager_ensure_instance_array_size_is_at_least => ensure_instance_array_size_is_at_least
implicit none
private
public :: create_error, create_errors
contains
function create_error(inv) result(res_instance_index)
!! Wrapper around `m_error_v_creation.create_error` (TODO: x-ref)
integer, intent(in) :: inv
!! Input value to use to create the error
!!
!! See docstring of `m_error_v_creation.create_error` for details.
!! [TODO: x-ref]
integer :: res_instance_index
!! Instance index of the result
!
! This is the major trick for wrapping.
! We return instance indexes (integers) to Python rather than the instance itself.
type(ErrorV) :: res, err
! Do the Fortran call
res = o_create_error(inv)
call error_v_manager_ensure_instance_array_size_is_at_least(1)
! Get the instance index to return to Python
call error_v_manager_get_available_instance_index(res_instance_index)
! Set the derived type value in the manager's array,
! ready for its attributes to be retrieved from Python.
err = error_v_manager_set_instance_index_to(res_instance_index, res)
!MZ: check for errors ?
end function create_error
function create_errors(invs, n) result(res_instance_indexes)
!! Wrapper around `m_error_v_creation.create_errors` (TODO: x-ref)
integer, dimension(n), intent(in) :: invs
!! Input value to use to create the error
!!
!! See docstring of `m_error_v_creation.create_error` for details.
!! [TODO: x-ref]
integer, intent(in) :: n
!! Number of values to create
integer, dimension(n) :: res_instance_indexes
!! Instance indexes of the result
!
! This is the major trick for wrapping.
! We return instance indexes (integers) to Python rather than the instance itself.
type(ErrorV) :: err
type(ErrorV), allocatable, dimension(:) :: res
integer :: i, tmp
! Lots of ways resizing could work.
! Optimising could be very tricky.
! Just do something stupid for now to see the pattern.
call error_v_manager_ensure_instance_array_size_is_at_least(n)
allocate(res(n))
! Do the Fortran call
! MZ: somenthing funny happens wheb res is an automatic array and
! not an allocatable one. LLMs and internet resorces I found are not
! completely clear to me. What seems to happen is that returning an array of derived types with allocatable
! components may generate hidden temporary arrays whose allocatable components
! become undefined (or the heap address gets corrupted) after the function returns.
res = o_create_errors(invs, n)
do i = 1, n
! Get the instance index to return to Python
call error_v_manager_get_available_instance_index(tmp)
! Set the derived type value in the manager's array,
! ready for its attributes to be retrieved from Python.
err = error_v_manager_set_instance_index_to(tmp, res(i))
!MZ: check for errors ?
! Set the result in the output array
res_instance_indexes(i) = tmp
end do
end function create_errors
end module m_error_v_creation_w