Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28457 Discussions

call fortran function from c using bind(c)

Addison
Beginner
287 Views
Hi, all

Ihave a problem when call Fortran function from c using bind (c), e.g.

Fortran function(mean.f90):

real, function mean(x)
real,dimension(:),intent(in) :: x
integer :: n
n=size(x)
mean=0.
do i=1,n
mean=mean+x(i)
enddo
mean=mean/real(n)
end function mean


communication function between c and fortran (c_mean.f90):

real(c_float), function c_mean(n,x) bind(c)
use, intrinsic :: iso_c_binding
integer(c_int),intent(in),value :: n
real(c_float), intent(in) :: x(n)

c_mean=mean(x)

end function c_mean


c program to call communication function (test.c)

#include
#include
float c_mean(int n, float *x);
main() {

float Y,x[10];
int i;
for (i=0; i<10; i++) {
x=i;
}
Y=c_mean1(10,x);

return 0;
}


compile and link in IVF and VC:
ifort mean.f90 c_mean.f90 /c
cl test.c mean.obj c_mean.obj
will give test.exe out.

but when I run test.exe there is an error window popup. I know the reason is that I used
"real,dimension(:),intent(in) :: x" in the mean.f90. If I use mean(n,x) as the fortran function, there is no this problem.

Thus my question is: can I call Fortran functions like mean.f90 from c? If I can, how do I change my c/fortran codes?

Thanks!

Addison

0 Kudos
3 Replies
Jugoslav_Dujic
Valued Contributor II
287 Views
Quoting - A Aa
Hi, all

Ihave a problem when call Fortran function from c using bind (c), e.g.

Fortran function(mean.f90):

real, function mean(x)
real,dimension(:),intent(in) :: x

communication function between c and fortran (c_mean.f90):

real(c_float), function c_mean(n,x) bind(c)
c_mean=mean(x)
end function c_mean


but when I run test.exe there is an error window popup. I know the reason is that I used
"real,dimension(:),intent(in) :: x" in the mean.f90. If I use mean(n,x) as the fortran function, there is no this problem.

Thus my question is: can I call Fortran functions like mean.f90 from c? If I can, how do I change my c/fortran codes?


You don't have a C<->Fortran problem; you actually have a Fortran<->Fortran problem.

Search for "Explicit interfaces" in your IVF online help, and find the page "Determining When Procedures Require Explicit Interfaces". The second item reads "A dummy argument that is an assumed-shape array".

Explicit interfaces are a very important concept in Fortran-90, so please read it thoroughly. Experienced Fortran-9x programmers tend to use them always (even when not strictly needed), because they ensure correct calling sequence between the calling and called procedures.

The best method to provide an explicit interface is USE association, i.e. to put the callee in a module, and let the caller USE that module. The following Fortran code will work as expected (when your syntax errors are fixed):
[cpp]module m_test
!=================================================
contains
!=================================================
real function mean(x)
real,dimension(:),intent(in) :: x
integer :: n
n=size(x)
mean=0.
do i=1,n
  mean=mean+x(i)
enddo
mean=mean/real(n)
end function mean

end module m_test
!=================================================
real(c_float) function c_mean(n,x) bind(c)
use, intrinsic :: iso_c_binding
USE M_TEST
integer(c_int),intent(in),value :: n
real(c_float), intent(in) :: x(n)

c_mean=mean(x)

end function c_mean[/cpp]



0 Kudos
Addison
Beginner
287 Views
Quoting - Jugoslav Dujic

You don't have a C<->Fortran problem; you actually have a Fortran<->Fortran problem.

Search for "Explicit interfaces" in your IVF online help, and find the page "Determining When Procedures Require Explicit Interfaces". The second item reads "A dummy argument that is an assumed-shape array".

Explicit interfaces are a very important concept in Fortran-90, so please read it thoroughly. Experienced Fortran-9x programmers tend to use them always (even when not strictly needed), because they ensure correct calling sequence between the calling and called procedures.

The best method to provide an explicit interface is USE association, i.e. to put the callee in a module, and let the caller USE that module. The following Fortran code will work as expected (when your syntax errors are fixed):
[cpp]module m_test
!=================================================
contains
!=================================================
real function mean(x)
real,dimension(:),intent(in) :: x
integer :: n
n=size(x)
mean=0.
do i=1,n
  mean=mean+x(i)
enddo
mean=mean/real(n)
end function mean

end module m_test
!=================================================
real(c_float) function c_mean(n,x) bind(c)
use, intrinsic :: iso_c_binding
USE M_TEST
integer(c_int),intent(in),value :: n
real(c_float), intent(in) :: x(n)

c_mean=mean(x)

end function c_mean[/cpp]




Thanks. It work now.
0 Kudos
Addison
Beginner
287 Views
Quoting - Jugoslav Dujic

You don't have a C<->Fortran problem; you actually have a Fortran<->Fortran problem.

Search for "Explicit interfaces" in your IVF online help, and find the page "Determining When Procedures Require Explicit Interfaces". The second item reads "A dummy argument that is an assumed-shape array".

Explicit interfaces are a very important concept in Fortran-90, so please read it thoroughly. Experienced Fortran-9x programmers tend to use them always (even when not strictly needed), because they ensure correct calling sequence between the calling and called procedures.

The best method to provide an explicit interface is USE association, i.e. to put the callee in a module, and let the caller USE that module. The following Fortran code will work as expected (when your syntax errors are fixed):
[cpp]module m_test
!=================================================
contains
!=================================================
real function mean(x)
real,dimension(:),intent(in) :: x
integer :: n
n=size(x)
mean=0.
do i=1,n
  mean=mean+x(i)
enddo
mean=mean/real(n)
end function mean

end module m_test
!=================================================
real(c_float) function c_mean(n,x) bind(c)
use, intrinsic :: iso_c_binding
USE M_TEST
integer(c_int),intent(in),value :: n
real(c_float), intent(in) :: x(n)

c_mean=mean(x)

end function c_mean[/cpp]




Thanks. It works now.
0 Kudos
Reply