Skip to content

Interop

Source: examples/interop/

fortran_library provides CcInfo, enabling bidirectional linking between Fortran and C/C++ targets.

2.A. fortran-calling-c

interop/
├── BUILD.bazel
├── c_math.c
├── c_math.h
└── fortran_calls_c.f90
c
#ifndef C_MATH_H
#define C_MATH_H

/**
 * Simple C math function for testing C/Fortran interop.
 * Adds two double precision numbers.
 *
 * @param a First number
 * @param b Second number
 * @return Sum of a and b
 */
double c_add_doubles(double a, double b);

#endif /* C_MATH_H */
c
#include "c_math.h"

double c_add_doubles(double a, double b) {
    return a + b;
}
fortran
program fortran_calls_c
    use iso_c_binding, only: c_double
    implicit none

    ! Interface to C function
    interface
        function c_add_doubles(a, b) bind(c, name="c_add_doubles")
            import :: c_double
            real(c_double), value :: a, b
            real(c_double) :: c_add_doubles
        end function c_add_doubles
    end interface

    ! Test variables
    real(c_double) :: result

    ! simple addition
    result = c_add_doubles(2.0d0, 3.0d0)
    if (abs(result - 5.0d0) > 1.0d-10) then
        print *, "FAIL: c_add_doubles(2.0, 3.0) = ", result, " expected 5.0"
    else
        print *, "PASS: c_add_doubles(2.0, 3.0) = 5.0"
    end if

end program fortran_calls_c
starlark
cc_library(
    name = "c_math",
    srcs = ["c_math.c"],
    hdrs = ["c_math.h"],
)

fortran_test(
    name = "fortran_calls_c",
    srcs = ["fortran_calls_c.f90"],
    deps = [":c_math"],
)
bash
bazel run //interop:fortran_calls_c
PASS: c_add_doubles(2.0, 3.0) = 5.0

2.B. c-calling-fortran

interop/
├── BUILD.bazel
├── c_calls_fortran.c
└── fortran_math.f90
fortran
module fortran_math_mod
    use iso_c_binding, only: c_double
    implicit none

contains

    ! Function callable from C
    ! The bind(c, name="...") attribute ensures C-compatible name mangling
    function fortran_square(x) bind(c, name="fortran_square")
        real(c_double), value :: x  ! value attribute for pass-by-value (C convention)
        real(c_double) :: fortran_square

        fortran_square = x * x
    end function fortran_square

end module fortran_math_mod
c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// use bind(c) to ensure C-compatible name mangling.
extern double fortran_square(double x);

int main(void) {
    int errors = 0;

    double result1 = fortran_square(5.0);
    if (fabs(result1 - 25.0) > 1e-10) {
        printf("FAIL: fortran_square(5.0) = %f, expected 25.0\n", result1);
        errors++;
    } else {
        printf("PASS: fortran_square(5.0) = 25.0\n");
    }
}
starlark
fortran_library(
    name = "fortran_math",
    srcs = ["fortran_math.f90"],
)

cc_test(
    name = "c_calls_fortran",
    srcs = ["c_calls_fortran.c"],
    deps = [":fortran_math"],
)
bash
bazel run //interop:c_calls_fortran
PASS: fortran_square(5.0) = 25.0