Fortran
meshio++ ships a modern object-oriented Fortran 2008 module, meshioplusplus, layered on the C API via ISO_C_BINDING — in the HDF5/PETSc style, aimed at Fortran HPC codes:
use meshioplusplus
type(mio_mesh) :: m
call m%read("bracket.msh")
print *, m%num_points(), "points,", m%num_cell_blocks(), "cell blocks"
call m%write("bracket.vtu")
call m%free()Building
build/configure.sh --fortran --build # implies --c-api
cmake --install build/cpp-release --prefix /opt/meshioplusplusinstalls libmeshioplusplus_fortran.so next to libmeshioplusplus.so, plus include/meshioplusplus/fortran/meshioplusplus.mod and the module source meshioplusplus.f90. Compile and link:
gfortran my_solver.f90 -I /opt/meshioplusplus/include/meshioplusplus/fortran \
-L /opt/meshioplusplus/lib -lmeshioplusplus_fortran -lmeshioplusplus -o my_solver.mod files are compiler-specific
A .mod compiled by gfortran N is unreadable by gfortran N±2, ifort, or flang. If your compiler rejects the installed .mod, recompile the module from the installed meshioplusplus.f90 with your own compiler and link the same libraries — that is exactly why the source is installed (the HDF5 approach). CMake consumers can instead find_package(meshioplusplus) and link meshioplusplus::meshioplusplus_fortran from the same build.
Array layout and 1-based indexing
The C core stores points as row-major (num_points, dim) and connectivity as (num_cells, nodes_per_cell). Because Fortran is column-major, the same memory is naturally the Fortran arrays
real(real64) :: points(dim, num_points) ! points(:, i) = coordinates of point i
integer(int64) :: conn(nodes_per_cell, num_cells)so nothing is ever transposed. Node indices are 1-based in this module; the ±1 shift happens inside the copying setters/getters (where a copy is made anyway):
call m%set_points(points) ! copies
call m%add_cell_block("tetra", conn) ! copies, shifts to the core's 0-based
call m%get_cell_block(1, rconn) ! allocates, copies, shifts back to 1-basedVector data uses the same rule — a per-point field of c components is data(c, num_points) in Fortran and round-trips as the C API's (num_points, c).
Zero-copy borrows exist where no index shift is needed:
real(real64), pointer :: p(:, :)
call m%points_ptr(p) ! p(dim, num_points) aliases mesh memory --
! valid until the next mutating call or m%free()Error handling
Every fallible procedure takes optional stat and errmsg arguments:
integer :: ierr
character(:), allocatable :: msg
call m%read("missing.vtu", stat=ierr, errmsg=msg)
if (ierr /= 0) print *, "read failed: ", msgIf stat is absent and the call fails, the message is printed and the program error stops — convenient for straight-line tools, pass stat when you need to recover. mio_error_message() returns the most recent failure message on the calling thread.
API summary
| Lifecycle | m%create() (implicit in read/setters), m%read(path [, format]), m%write(path [, format]), m%free(), m%is_valid() |
| Building | m%set_points(points), m%add_cell_block(type, conn) (int32 or int64), m%add_point_data(name, data) (rank-1 or rank-2), m%add_cell_data(name, data) (once per block, in order), m%add_field_data(name, data) |
| Counts | m%num_points(), m%point_dim(), m%num_cell_blocks(), m%num_point_data(), m%num_cell_data(), m%num_field_data(), m%cell_data_num_blocks(name) |
| Cell blocks (1-based) | m%cell_block_type(i), m%cell_block_num_cells(i), m%cell_block_nodes_per_cell(i), m%cell_block_is_ragged(i), m%get_cell_block(i, conn) |
| Data (copies, real64) | m%get_points(points), m%get_point_data(name, data) (rank-1 or rank-2), m%get_cell_data(name, block, data), m%get_field_data(name, data); names via m%point_data_name(i) etc. (sorted order) |
| Zero-copy | m%points_ptr(p) |
| Module-level | mio_convert(in, out [, in_format, out_format]), mio_version(), mio_mesh_backend(), mio_format_readable(f), mio_format_writable(f), mio_error_message() |
The complete CI-tested example lives at doc/examples/fortran_example.f90; format support and the v1 limitations (ragged blocks, side-channel metadata) are identical to the C API, which this module wraps. Copy-getters deliver real(real64) regardless of the stored dtype (float32/int32/int64 are converted); Fortran on Windows/MSVC is untested in v1.