Fortran ↔ C Interoperability with ISO_C_BINDING: Design & Checks
A concise guide to using Fortran’s ISO_C_BINDING for safe, minimal interoperation with C, covering design, checks, failure scenarios.
24 Sept 2025, 20:56 UTC

Requirements
To call a C routine from Fortran you need:
- Both compilers support the ISO_C_BINDING module (Fortran 2003+).
- Matching C types for the arguments and return value; use the C‑compatible types defined in ISO_C_BINDING (e.g.,
C_INT,C_FLOAT). - Consistent name mangling – the Fortran call must reference the exact C symbol name.
Smallest Viable Design
The minimal design declares the external C function once in Fortran, marks it with BIND(C), and calls it directly. No wrapper libraries or additional Fortran modules are required.
!< Fortran module that calls a C add function >
module c_add_mod
use, intrinsic :: iso_c_binding, only: c_int
implicit none
interface
function c_add(a, b) bind(C, name="c_add") result(res) bind(C)
import :: c_int
integer(c_int), value :: a, b
integer(c_int) :: res
end function
end interface
end module
program test_c_add
use c_add_mod
implicit none
integer(c_int) :: x, y, z
x = 5_c_int
y = 7_c_int
z = c_add(x, y)
print *, "5 + 7 =", z
end program
On the C side you need a matching definition:
/* c_add.c */
#include <stdint.h>
int32_t c_add(int32_t a, int32_t b) { return a + b; }
Trust & Data Boundaries
The Fortran code assumes the C library follows the C ABI: correct calling convention, stack alignment, and type sizes. The boundary is a single function call; the Fortran side must validate any data returned from C if it is used in a context that could cause undefined behavior (e.g., assuming a non‑null string).
Operational Checks
- Compile‑time type checking: The compiler will reject mismatched types if you use ISO_C_BINDING types. Use
-Wall -Wextrato catch hidden mismatches. - Runtime bounds checking: With
-fcheck=all(gfortran) or equivalent flags you can detect out‑of‑bounds array accesses that might be caused by a C routine. - Alignment & aliasing flags: Use
-fno-strict-aliasingor the compiler’s aliasing option to avoid subtle bugs when the C routine accesses Fortran arrays. - Name mangling verification: Compile the C file and run
nmto confirm the symbol name isc_add.
Failure Modes
- Name mangling mismatch: If the Fortran
BIND(C, name="c_add")does not match the C symbol, the call will fail at link time or result in a segmentation fault. - Type size mismatch: Using
INTEGER(C_INT)assumesint32_ton the C side; on a platform whereintis 64 bits this will corrupt data. - Derived type layout: A Fortran derived type marked
BIND(C)must have only interoperable components. Mixing non‑interoperable components leads to undefined layout. - String handling: Fortran CHARACTER is not null‑terminated; passing a Fortran string to a C function expecting
char*without length can overflow. - Stack alignment differences: On 64‑bit targets the stack must be 16‑byte aligned for C; a Fortran compiler that misaligns the stack will cause crashes.
When to Redesign
- Target compiler lacks ISO_C_BINDING support (e.g., old legacy Fortran compilers).
- The C library uses C++ name mangling or templates – the interface must be wrapped in extern "C".
- Performance critical code needs inline assembly or non‑C ABI interactions; a direct C call may be too slow.
- You need to expose Fortran code to other languages; a pure C interface is a lower‑level abstraction that may not suffice.
Practical Checklist
- Define all C‑compatible types using ISO_C_BINDING.
- Use
BIND(C, name="...")to fix the symbol name. - Compile the C source with
gcc -c c_add.c -o c_add.oand the Fortran source withgfortran -c test_c_add.f90 -o test_c_add.o. - Link both objects:
gfortran test_c_add.o c_add.o -o test_c_add. - Run the program and verify the output matches the expected result.
- Optionally, run
nm test_c_add | grep c_addto confirm the symbol is present.
Example Verification Steps
# Compile C
gcc -c c_add.c -o c_add.o
# Compile Fortran
gfortran -c test_c_add.f90 -o test_c_add.o
# Link
gfortran test_c_add.o c_add.o -o test_c_add
# Run
./test_c_add
# Expected output: 5 + 7 = 12
After running, inspect the stack alignment with a debugger or gdb ./test_c_add if you suspect alignment issues. If the program crashes, check the symbol name with nm c_add.o and verify that the Fortran BIND(C, name="c_add") matches.
Conclusion
ISO_C_BINDING offers a minimal, standards‑compliant path to interoperate with C. By strictly using the provided types, binding attributes, and performing the outlined checks you can achieve reliable, maintainable cross‑language code. When the design assumptions break—such as missing ISO_C_BINDING support or the need for C++ mangling—consider a wrapper layer or a redesign that isolates the Fortran code from the changing ABI.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.