Types¶
Numeric Types¶
The numeric types usually require no conversion. In this case the type map is mainly used to generate declaration code for wrappers:
type: int
fields:
c_type: int
cxx_type: int
f_type: integer(C_INT)
f_kind: C_INT
f_module:
iso_c_binding:
- C_INT
f_cast: int({f_var}, C_INT)
One case where a conversion is required is when the Fortran argument
is one type and the C++ argument is another. This may happen when an
overloaded function is generated so that a C_INT
or C_LONG
argument may be passed to a C++ function function expecting a
long
. The f_cast field is used to convert the argument to the
type expected by the C++ function.
Bool¶
The first thing to notice is that f_c_type is defined. This is
the type used in the Fortran interface for the C wrapper. The type
is logical(C_BOOL)
while f_type, the type of the Fortran
wrapper argument, is logical
.
The f_statements section describes code to add into the Fortran
wrapper to perform the conversion. c_var and f_var default to
the same value as the argument name. By setting c_local_var, a
local variable is generated for the call to the C wrapper. It will be
named SH_{f_var}
.
There is no Fortran intrinsic function to convert between default
logical
and logical(C_BOOL)
. The pre_call and
post_call sections will insert an assignment statement to allow
the compiler to do the conversion.
If a function returns a bool
result then a wrapper is always needed
to convert the result. The result section sets need_wrapper
to force the wrapper to be created. By default a function with no
argument would not need a wrapper since there will be no pre_call
or post_call code blocks. Only the C interface would be required
since Fortran could call the C function directly.
See example checkBool.
Char¶
Any C++ function which has char
or std::string
arguments or
result will create an additional C function which include additional
arguments for the length of the strings. Most Fortran compiler use
this convention when passing CHARACTER
arguments. Shroud makes
this convention explicit for two reasons:
- It allows an interface to be used. Functions with an interface will not pass the hidden, non-standard length argument, depending on compiler.
- Returning character argument from C to Fortran is non-portable.
The C wrapper will create a NULL terminated copy a string with the intent(in) attribute. The assumption is that the trailing blanks are not part of the data but only padding. Return values and intent(out) arguments add a len annotation with the assumption that the wrapper will copy the result and blank fill the argument so it need to know the declared length.
A buffer for intent(out) arguments is also create which is one longer than the Fortran string length. This allows space for a C terminating NULL. This buffer is passed to the C library which will copy into it. Upon return, the buffer is copied and blank filled into the user’s argument and the intermediate buffer released.
Library functions which return a scalar char
have a wrapper generated
which pass a char *
argument to the C wrapper where the first
element is assigned ( *arg
a.k.a arg[0]
). Returning a char
proved to be non-portable while passing the result by reference works
on the tested compilers.
The bufferify function will be named the same as the original function with the option C_bufferify_suffix appended to the end. The Fortran wrapper will use the original function name, but call the C wrapper which accepts the length arguments.
Python wrappers may need an additional attribute for intent(out)
strings to let Shroud know how much space to pass to the function. A
function may pass a char *
argument which the C library will copy
into. While this is not a recommened practice since it’s easy to
overwrite memory, Shoud can deal with it by setting the +charlen(n)
attribute where n is the number of character in the array passed to
the function. This is required for Python since strings are inmutable.
The buffer will be converted into a Python str object then returned to
the user. This is not an issue in Fortran since the output buffer is
passed in by the caller and will have a known size.
By default, a Fortran blank input string will be converted to an empty
string before being passed to the C library. i.e. " "
in Fortran
is converted to '\0'
in C. This behavior can be changed to convert
the empty string into a NULL
pointer by setting the +blanknull
attribute. This is often more natural for the C library to indicate the
absence of a value. The option F_blanknull can be used to make this the
default for all const char *
arguments.
On some occasions the copy and null terminate behavior is not wanted. For example, to avoid copying a large buffer or the memory must be operated on directly. In this case using the attribute +api(capi) will use the native C API instead of the bufferify API for the argument. The library will need some way to determine the length of the string since it will not be passed to the C wrapper. As an alternative the bufferify function can be avoided altogether by setting the F_create_bufferify_function option to false.
The character type maps use the c_statements section to define code which will be inserted into the C wrapper. These actions vary depending on the intent of in, out, inout and result.
MPI_Comm¶
MPI_Comm is provided by Shroud and serves as an example of how to wrap a non-native type. MPI provides a Fortran interface and the ability to convert MPI_comm between Fortran and C. The type map tells Shroud how to use these routines:
type: MPI_Comm
fields:
cxx_type: MPI_Comm
c_header: mpi.h
c_type: MPI_Fint
f_type: integer
f_kind: C_INT
f_c_type: integer(C_INT)
f_c_module:
iso_c_binding:
- C_INT
cxx_to_c: MPI_Comm_c2f({cxx_var})
c_to_cxx: MPI_Comm_f2c({c_var})
This mapping makes the assumption that integer
and
integer(C_INT)
are the same type.