|
| 1 | +module assumed_module ! i added this |
| 2 | + use, intrinsic :: iso_c_binding |
| 3 | + ! Assume this code is inside a module |
| 4 | + |
| 5 | + type random_stream |
| 6 | + ! A (uniform) random number generator (URNG) |
| 7 | + contains |
| 8 | + procedure(random_uniform), deferred, pass(stream) :: next |
| 9 | + ! Generates the next number from the stream |
| 10 | + end type random_stream |
| 11 | + |
| 12 | + abstract interface |
| 13 | + ! Abstract interface of Fortran URNG |
| 14 | + subroutine random_uniform(stream, number) |
| 15 | + import :: random_stream, c_double |
| 16 | + class(random_stream), intent(inout) :: stream |
| 17 | + real(c_duoble), intent(out) :: number |
| 18 | + end subroutine random_uniform |
| 19 | + end interface |
| 20 | + |
| 21 | + type :: urng_state ! No BIND(C), as this type is not interoperable |
| 22 | + class(random_stream), allocatable :: stream |
| 23 | + end type urng_state |
| 24 | + |
| 25 | +contains ! i added this |
| 26 | + subroutine initialize_urng(state_handle, method) & |
| 27 | + bind(c, name="InitializeURNG") |
| 28 | + type(c_ptr), intent(out) :: state_handle |
| 29 | + ! An opaque handle for the URNG |
| 30 | + character(c_char), dimension(*), intent(in) :: method |
| 31 | + ! The algorithm to be used |
| 32 | + type(urng_state), pointer :: state |
| 33 | + ! An actual URNG object |
| 34 | + allocate(state) |
| 35 | + ! There needs to be a corresponding finalizatin |
| 36 | + ! procedure to avoid memory leaks, not shown in this example |
| 37 | + ! Allocate state%stream with a dynamic type depending on method |
| 38 | + |
| 39 | + state_handle=c_loc(state) |
| 40 | + ! Obtain an opaque handle to return to C |
| 41 | + end subroutine initialize_urng |
| 42 | + |
| 43 | + ! Generate a random number: |
| 44 | + subroutine generate_uniform(state_handle, number) & |
| 45 | + bind(c, name="GenerateUniform") |
| 46 | + type(c_ptr), intent(in), value :: state_handle |
| 47 | + ! An opaque handle: Obained via a call to initialize_urng |
| 48 | + real(c_double), intent(out) :: number |
| 49 | + |
| 50 | + type(urng_state), pointer :: state |
| 51 | + ! A pointer to the actual urng |
| 52 | + |
| 53 | + call c_f_pointer(c_ptr=state_handle, fptr=state) |
| 54 | + ! Convert the opaque handle into a usable pointer |
| 55 | + call state%stream%next(number) |
| 56 | + ! Use the type-bound procedure next to generate number |
| 57 | + end subroutine generate_uniform |
| 58 | +end module assumed_module |
| 59 | + |
| 60 | + |
0 commit comments