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

binding c functions returning structs

codorniz
Beginner
508 Views
Hi,

the following code lines could be an example of how to bind C functions that return structs.
But I have got a question you will see below.

Well, first I read information behind this link:
calling C procedures from an Intel Fortran Program

Then I wrote... (One needs to consider a lot of things when passing strings, arras or vectors from fortran to C, I thought structs were easier)

The C file: cfun.c

#include

typedef struct { double INF, SUP; } interval;

double cp_dbl_(double*);
interval cp_iv_(interval*);

void cp2_iv_(interval*, interval*);


double cp_dbl_(double *arg) // double function
{
printf("arg : %lf\n", *arg);
return *arg;
}


interval cp_iv_(interval *arg) // interval function
{
interval res;
printf("inf: %lf, sup: %lf\n", (*arg).INF, (*arg).SUP);
res.INF= (*arg).INF;
res.SUP= (*arg).SUP;
return res;
}


void cp2_iv_(res, arg) // interval function 2
interval *res, *arg;
{
printf("res, inf: %lf, sup: %lf\n", (*res).INF, (*res).SUP);
if ( arg ) {
printf("arg, inf: %lf, sup: %lf\n", (*arg).INF, (*arg).SUP);
res->INF= (*arg).INF;
res->SUP= (*arg).SUP;
} else {
printf("error: missing parameter\n");
}
return;
}


the fortran file: test1.f90

module mod_tsqr
use ISO_C_BINDING

type, BIND(C) :: interval
real(C_DOUBLE) :: INF
real(C_DOUBLE) :: SUP
end type interval
end module mod_tsqr


program test
use mod_tsqr
implicit none

interface cp
function cp_iv(a) bind(c,name="cp_iv_")
use mod_tsqr
type(interval) :: cp_iv
type(interval), intent(in) :: a
end function

function cp_dbl(a) bind(c,name="cp_dbl_")
use mod_tsqr
real(C_DOUBLE) :: cp_dbl
real(C_DOUBLE), intent(in) :: a
end function
end interface

real(C_DOUBLE) :: u, v
type(interval) :: x, f

u= 12.3_fpkind
write(*,*) 'double: x =', u
write(*,*)
write(*,*) 'C Function: copy double'
v= -3.0
v = cp(u)
write(*,*) 'f =', v


write(*,*)
write(*,*)
x = interval(0d0,1d0)
write(*,*) 'Interval: x =', x
write(*,*)
write(*,*) 'C Function: copy interval'
f = interval(27d0,27d0)
f = cp(x)
write(*,*) 'f =', f
end program



Then I compiled and linked both files with 3 different versions of ifort. (latest: 11.0.083)
Basically the double value is copied and interval is not copied.

With gfortran and g95 it works.

I found a workarround for this problem (pls. see below), but i do not like it too much. The reason: the small project I am working on, shall be supported on various systems, therefore we have to write the code compiler independent (as far as this is possible).

So my question: Can I make the test1.f90 work somehow? Or ist there a flag, that helps?
(unfortunately I believe to have found an answer already. In the Fortran 2008 standard that seems to be discussed.)


my workarround: test2.f90


module mod_tsqr
use ISO_C_BINDING
integer, parameter :: fpkind = kind(0.0d0)

type, BIND(C) :: interval
real(C_DOUBLE) :: INF
real(C_DOUBLE) :: SUP
end type interval
end module mod_tsqr


program test
use mod_tsqr
implicit none

interface
function cp2_iv(a) bind(c,name="cp2_iv_")
use mod_tsqr
type(interval) :: cp2_iv
type(interval), intent(in) :: a
end function
end interface

type(interval) :: x, f

x = interval(0d0,1d0)
write(*,*) 'Interval: x =', x

write(*,*)
write(*,*) 'C Function 2: copy interval in C'
f = interval(27d0,27d0)
f = cp2_iv(x)
write(*,*) 'f =', f
end program



Thanks a lot for reading!
0 Kudos
1 Reply
Steven_L_Intel1
Employee
508 Views
We have had errors in BIND(C), especially relating to functions where C and Fortran have different conventions. In 11.1 Update 2, we resolved many of these issues and your original program seems to work ok, though I know some errors remain.
0 Kudos
Reply