13.12. C and Fortran Bindings

The C and Fortran (mpi_f08) bindings are generated from Python code in ompi/mpi/bindings. Both the language bindings are generated from template files for each function. In the C case, each template file corresponds to a single generated C file, while in the Fortran case there are three major files generated for all functions.

The Python code depends on special prototype lines used with both the C and Fortran bindings. These “prototypes” are designed to be easy to parse and use specific type constants that can be mapped directly to the expanded language-specific code, error-handling, and conversion code.

13.12.1. C Bindings

This will walk through adding (or converting) a plain-C binding into a templated version controlled by the script.

As an example, for MPI_Send you might have a C file that looks something like this:

#include "ompi_config.h"
...other includes...

int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest,
             int tag, MPI_Comm comm)
{
    ...internal checks...
    return internal_mpi_send(buf, count, datatype, dest, tag, comm);
}

To convert this to a template, you will have to first ensure that only a single function is defined in the file, removing or abstracting out static functions, and separating multiple definitions, such as MPI_Send and MPI_Isend, into different files. The template should also not include any macro-processing that attempts to change the name of the function or parameter types; this code should be generated by the script, or abstracted into header files that can work easily with multiple functions.

At this point, the template should look like the example above, with a “header” section, with simple includes or macros, maybe a static global, and the function defintion and nothing else.

The next step is to convert the signature line into the prototype format that the script expects. For MPI_Send, this should look something like this:

PROTOTYPE ERROR_CLASS send(BUFFER buf, COUNT count, DATATYPE type, RANK dest,
                           TAG tag, COMM comm)

Notice how the function name is changed, the MPI_ prefix removed and the rest converted to lowercase, and also how each parameter is simplified into a TYPE name format, where the TYPE conforms to an allowed list in ompi/mpi/bindings/ompi_bindings/c_type.py. For newer functions and types, you may have to extend the c_type.py file with a new class showing how to handle the type.

The final step is to update Makefile.am, adding the template name, in this case send.c.in, to the prototype_sources variable, and the generated file name, generated_send.c, to interface_profile_sources. The generated file name must be of the form generated_${basename}.c, where ${basename} is the name of the template file stripped of all extensions.

13.12.2. Fortran Bindings

Adding new Fortran bindings follows a similar process to the C version above. All new interfaces are actually based on a single C-template file following the same format as the C interface templates. However, the C file generated will use Fortran-specific arguments, including CFI_* arguments, when TS 29113 is enabled, MPI_Fint * arguments in other cases, and others specific to how the Fortran MPI types are defined. Most of these files perform Fortran-specific error handling, Fortran-to-C type conversion, and other necessary steps before calling the actually C bindings with the proper arguments.

These templates are used not only to generate a C backing file for the Fortran code, but also the Fortran interface definitions and the Fortran subroutines corresponding to the generated C file. These are output in three separate files:

  • ompi/mpi/fortran/use-mpi-f08/api_f08_generated.F90

  • ompi/mpi/fortran/use-mpi-f08/base/api_f08_generated.c

  • ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces-generated.h

The Fortran file api_f08_generated.F90 contains all the internal subroutine definitions, each of which makes a call into corresponding C functions. The internal subroutine names are mapped to the external interface, including multiple interfaces for the bigcount version of functions, in mpi-f08-interfaces-generated.h. The C file api_f08_generated.c basically contains a concatenation of all fully expanded C templates. These files contain preprocessing directives to ensure they can support compilers with and without TS 29113 support, allowing use of CFI_cdesc_t types when available (see Fortran 2018 for more details).

If a new type needs to be added, then one will need to extend fortran_type.py in ompi/mpi/bindings/ompi_bindings with an additional type class specifying how to handle the type in the above generated files, including any required key-value attributes for more complicated types. New types use a Type base class with functions that can be implemented by derived classes, each returning expanded Fortran or C code.

13.12.3. Other Considerations

Keep in mind that the generated files will not be deleted with a make clean or make distclean; instead use make maintainer-clean to delete those.