- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
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!
Link Copied
1 Reply
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page