Integrating C Libraries into Fortran with ISO_C_BINDING: A Step‑by‑Step Guide
Learn how to call C libraries from Fortran using ISO_C_BINDING. Follow a clear step‑by‑step guide, verify symbol visibility, and recover from common pitfalls like name mangling and type mismatches.
16 Apr 2026, 07:08 UTC

Problem & Takeaway
When you need to reuse a mature C library in a Fortran project, you must avoid name mangling, type mismatches, and ABI incompatibilities. The ISO_C_BINDING module gives you a portable, compile‑time way to declare C‑compatible kinds, pointer types, and function interfaces. By following a clear procedure—compile the C code, write a Fortran interface with BIND(C), and link with matching compiler flags—you can call C functions directly from Fortran and verify the integration with simple tooling.
Prerequisites
- Fortran compiler supporting
ISO_C_BINDING(e.g.,gfortran9+). - Standard C compiler (e.g.,
gcc). - Basic knowledge of C and Fortran data types.
- Access to the C library source or pre‑compiled object files.
Desired Outcome
Produce a working executable that calls a C function from Fortran, prints the result, and passes basic diagnostics (symbol visibility, correct output, no runtime crashes).
Concrete Example
We’ll wrap a simple C function that adds two integers:
/* lib.c */
#include <stdio.h>
int add_ints(int a, int b) {
return a + b;
}
And call it from Fortran:
! main.f90
program use_c
use iso_c_binding, only: c_int, c_funptr, c_loc
implicit none
interface
function add_ints(a, b) bind(C, name="add_ints") result(res) bind(C)
import :: c_int
integer(c_int), value :: a, b
integer(c_int) :: res
end function add_ints
end interface
integer(c_int) :: x, y, z
x = 7_c_int
y = 5_c_int
z = add_ints(x, y)
print *, "Result: ", z
end program use_c
Step‑by‑Step Procedure
- Compile the C source into an object file.
# Compile with PIC for shared libs or static linking gcc -c -fPIC lib.c -o lib.o - Compile the Fortran source into an object file.
gfortran -c main.f90 -o main.o - Link both objects into a single executable.
gfortran main.o lib.o -o demo - Run the program to verify output.
./demo # Expected output: Result: 12 - Check symbol visibility.
nm demo | grep add_ints # Should list a symbol like 0000000000000000 T add_ints - Optional: Verify ABI with objdump.
objdump -d demo | less # Search for the call to add_ints to confirm correct calling convention.
Expected Checks
- Symbol name. Use
nmorobjdumpto confirm the C function appears asadd_ints(no underscore or mangling). If it shows_add_intsor similar, adjust the FortranBIND(C, NAME='add_ints')or compile with-fno-underscoring. - Return value correctness. Compare the Fortran output against a known C program that prints the same result.
- Runtime stability. No segmentation faults or stack corruption should occur. If the program crashes, verify that the Fortran arguments are passed with the
valueattribute and that the C function signature matches.
Recovery Options
- Mismatch in integer kind. If the Fortran output is wrong, check that
c_intmatches the Cintsize on your platform. On 64‑bit systems,c_intis still 32‑bit; usec_longif the C function useslong. - Underscore prefix. If the symbol appears as
_add_ints, either:- Add
-fno-underscoringto the Fortran compile line. - Change the C function name to
add_ints_and update the FortranBIND(C, NAME='add_ints_').
- Add
- Structure alignment. For complex data, declare C structs with
__attribute__((packed))and useBIND(C)in Fortran to match layout. Verify withsizeofin C andc_sizeofin Fortran. - Linker errors. Ensure both object files are compiled with the same ABI flags (e.g.,
-std=c11for C and-std=f2008for Fortran). Mismatched flags can cause symbol resolution failures.
Limitations & Practical Checks
- ISO_C_BINDING only guarantees interoperability for scalar types and pointers. For arrays, use explicit shape or
c_ptrand manual copying. - Non‑interoperable types (e.g., Fortran
complexvs Cdouble complex) require a C wrapper that translates between representations. - When calling C functions that modify memory, ensure the Fortran arguments are passed by reference (
intent(inout)) and use thevalueattribute only for scalars.
To confirm correct operation, run the compiled program and compare its output with a reference C program. If the output matches and no linker or runtime errors occur, the integration is considered successful.
Diagram
| Component | Role |
|---|---|
| C Source (lib.c) | Defines native functions. |
| Fortran Interface (main.f90) | Declares C functions with ISO_C_BINDING. |
| Compiler Flags | Ensures matching ABI and symbol naming. |
| Linker | Combines object files into executable. |
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.