Fortran¶
This section discusses Fortran specific wrapper details. This will also include some C wrapper details since some C wrappers are created specificially to be called by Fortran.
Wrapper¶
As each function declaration is parsed a format dictionary is created with fields to describe the function and its arguments. The fields are then expanded into the function wrapper.
The template for Fortran code showing names which may be controlled directly by the input YAML file:
module {F_module_name}
! use_stmts
implicit none
abstract interface
subprogram {F_abstract_interface_subprogram_template}
type :: {F_abstract_interface_argument_template}
end subprogram
end interface
interface
{F_C_pure_clause} {F_C_subprogram} {F_C_name}
{F_C_result_clause} bind(C, name="{C_name}")
! arg_f_use
implicit none
! arg_c_decl
end {F_C_subprogram} {F_C_name}
end interface
interface {F_name_generic}
module procedure {F_name_impl}
end interface {F_name_generic}
contains
{F_subprogram} {F_name_impl}
decl_args
declare ! local variables
pre_call
call {arg_c_call}
post_call
end {F_subprogram} {F_name_impl}
end module {F_module_name}
Class¶
Use of format fields for creating class wrappers.
type, bind(C) :: {F_capsule_data_type}
type(C_PTR) :: addr = C_NULL_PTR ! address of C++ memory
integer(C_INT) :: idtor = 0 ! index of destructor
end type {F_capsule_data_type}
type {F_derived_name}
type({F_capsule_data_type}) :: {F_derived_member}
contains
procedure :: {F_name_function} => {F_name_impl}
generic :: {F_name_generic} => {F_name_function}, ...
! F_name_getter, F_name_setter, F_name_instance_get as underscore_name
procedure :: [F_name_function_template] => [F_name_impl_template]
end type {F_derived_name}
Standard type-bound procedures¶
Several type bound procedures can be created to make it easier to use class from Fortran.
Usually the F_derived_name is constructed from wrapped C++ constructor. It may also be useful to take a pointer to a C++ struct and explicitly put it into a the derived type. The functions F_name_instance_get and F_name_instance_set can be used to access the pointer directly.
Two predicate function are generated to compare derived types:
interface operator (.eq.)
module procedure class1_eq
module procedure singleton_eq
end interface
interface operator (.ne.)
module procedure class1_ne
module procedure singleton_ne
end interface
contains
function {F_name_scope}eq(a,b) result (rv)
use iso_c_binding, only: c_associated
type({F_derived_name}), intent(IN) ::a,b
logical :: rv
if (c_associated(a%{F_derived_member}%addr, b%{F_derived_member}%addr)) then
rv = .true.
else
rv = .false.
endif
end function {F_name_scope}eq
function {F_name_scope}ne(a,b) result (rv)
use iso_c_binding, only: c_associated
type({F_derived_name}), intent(IN) ::a,b
logical :: rv
if (.not. c_associated(a%{F_derived_member}%addr, b%{F_derived_member}%addr)) then
rv = .true.
else
rv = .false.
endif
end function {F_name_scope}ne