I'm trying to learn how to call a Fortran function or subroutine from a C program and I made this simple example:
The Fortran function area.f90 is
function Area_Circle(r)
implicit none
real(kind(1.d0)) , intent(out):: Area_Circle
real(kind(1.d0)), intent(in) :: r
real(kind(1.d0)), parameter :: Pi = acos(-1.d0)
Area_Circle = Pi * r * r
end function Area_Circle
and the C main.c program
#include <stdio.h>
extern double Area_Circle_(double *r);
int main(int argc, char **argv){
double r;
printf("Enter the radius\n");
scanf("%lf", &r);
printf("The area is %lf\n", Area_Circle_(&r));
return 0;
}
I tried to compile and build with the command
gcc -o app main.c area.f90 -lgfortran
and the exit is
area.f90:1:0:
function Area_Circle(r)
Error: Symbol at (1) is not a DUMMY variable
What should I do to compile and run correctly this?
P.D.: I don't usually work in Fortran but some of my colleagues yes. For this reason I want to learn Fortran-C interoperativity.
There are multiple things that need to be addressed.
Your Fortran function Area_Circle
is incorrect: The function name's type aka its return type cannot have an intent
.
There is a module defined in the Fortran standard which makes interoperability of Fortran-C well-defined and portable: iso_c_binding
. You should make use of it, e.g. note the bind(c)
attribute and the real kind c_double
.
Fortran is case-insensitive s.t. you need to call it in all lowercase in your C program, i.e. area_circle
instead of Area_Circle_
.
This behavior can be overridden by using bind(c, name="<some_name>")
.
The Fortran file area.f90
function Area_Circle(r) bind(c)
use, intrinsic :: iso_c_binding
implicit none
real(c_double), intent(in) :: r
real(c_double) :: Area_Circle
real(c_double), parameter :: PI = acos(-1.d0)
Area_Circle = PI * r * r
end function
The C file main.c
#include <stdio.h>
extern double area_circle(double *r);
int main(int argc, char **argv){
double r;
printf("Enter the radius\n");
scanf("%lf", &r);
printf("The area is %lf\n", area_circle(&r));
return 0;
}