Hi,
Could someone provide an example of using Fortran 2003 to call a C function.
Thanks,
Tuan
Hi,
Could someone provide an example of using Fortran 2003 to call a C function.
Thanks,
Tuan
Hi Tuan,
Here’s one of our internal test codes which shows how to use “bind(c)” in an interface block to tell Fortran that you’re calling a C routine. I don’t show all the ISO_C_BINDING data types, but they are all fully supported.
bind.f90
module test
integer N
parameter ( N = 28)
integer ND
parameter ( ND= 4 )
interface
subroutine plainc (a,b,c) bind(c, name = 'newc')
integer a,b
real c
end subroutine plainc
subroutine intfunc (a,b,c,d,e,f,g,h,i) bind(c)
integer, value :: a,b,c,d,e,f,g,h
integer *8, value :: i
end subroutine intfunc
subroutine logfunc (a,b,c,d,e,f,g,h) bind(c)
integer , value :: a,b,c,d
logical , value :: e,f,g,h
end subroutine logfunc
function realfunc (a,b,c,d,e,f,g,h,i) result(bind) bind(c)
real, value :: a,b,c,e,f,g,h
real *8, value :: i,d
integer bind
end function realfunc
subroutine check (a,b,c) bind (c)
integer a(N), b(N), c
end subroutine check
subroutine checkd (a,b,c) bind (c)
real*8 :: a(ND), b(ND)
integer :: c
end subroutine checkd
end interface
common /result/ a_array
integer a_array(N)
BIND (c) ::/result/
common /expect/ e_array
integer e_array(N)
BIND (c) ::/expect/
common /d_expect/ d_array
real *8 d_array(ND)
BIND (c) ::/d_expect/
common /d_result/ dr_array
real *8 dr_array(ND)
BIND (c) ::/d_result/
end module
use test
logical ll
real*8 tt
real bind
integer*8 kko
kko = 45
ll = .FALSE.
tt = 50.0
call plainc (1,2,4.0)
call intfunc(3,4,5,6,10,20,30,40,kko)
call logfunc(7,8,9,10,.TRUE., .FALSE., .TRUE. , .FALSE. )
a_array(25) = realfunc(2.0, 3.0, 4.0, tt,3.0,3.0,6.0,30.03E04,400.004D01)
call check(a_array, e_array , N)
call checkd(dr_array, d_array, ND)
end
bindc.c
/* C counterpart to test Fortran BIND(C) functions,
subroutines
*/
#include <stdio.h>
#define N 28
#define ND 4
extern int expect[N]= { /* newc */
0, 1, 2, 4,
/* intfunc */
3, 4, 5, 6, 10, 20, 30, 40, 45,
/* logfunc */
7, 8, 9, 10, -1, 0, -1, 0,
/* real func */
2.0, 3.0, 4.0, 22 , 3.0,
3.0, 6.0 };
extern double d_expect[ND]= { /* realfunc */
0.0, 300300.0, 4000.04, 50.0};
int result[N];
double d_result[ND];
void newc (int *a, int *b, float * kk) {
result[0] = 0;
result[1] = *a;
result[2] = *b;
result[3] = *kk;
}
void intfunc( int a, int b, int c, int d, char i1,
short i2, int i3, int i4, long long i8) {
result[4] = a;
result[5] = b;
result[6] = c;
result[7] = d;
result[8] = (int) i1;
result[9] = (int) i2;
result[10] = i3;
result[11] = i4;
result[12] = (int) i8;
}
void logfunc( int a, int b, int c, int d,
int i2, int i3, int i4, int i8) {
result[13] = a;
result[14] = b;
result[15] = c;
result[16] = d;
result[17] = i2;
result[18] = i3;
result[19] = i4;
result[20] = i8;
}
int realfunc( float a, float b, float c, double d,
float e, float f, float g,
float r4, double r8) {
result[21] = a;
result[22] = b;
result[23] = c;
result[24] = 0; /* f90 will store return val */
result[25] = e;
result[26] = f;
result[27] = g;
d_result[0] = 0.0;
d_result[1] = r4;
d_result[2] = r8;
d_result[3] = d;
return (22);
}
void
check(res, exp, np)
int *res, *exp, *np;
{
int i;
int n = *np;
int tests_passed = 0;
int tests_failed = 0;
for (i = 0; i < n; i++) {
if (exp[i] == res[i]) {
tests_passed ++;
} else {
tests_failed ++;
printf(
"test number %d FAILED. res %d(%08x) exp %d(%08x)\n",
i+1,res[i], res[i], exp[i], exp[i] );
}
}
if (tests_failed == 0) {
printf(
"%3d tests completed. %d tests PASSED. %d tests failed.\n",
n, tests_passed, tests_failed);
} else {
printf("%3d tests completed. %d tests passed. %d tests FAILED.\n",
n, tests_passed, tests_failed);
}
}
void
checkd(res, exp, np)
double *res, *exp;
int *np;
{
int i;
int n = *np;
int tests_passed = 0;
int tests_failed = 0;
for (i = 0; i < n; i++) {
if (exp[i] == res[i]) tests_passed ++;
else {
int j = (res[i] - exp[i]) * 1000.0;
tests_failed ++;
printf("test number %d FAILED. double prec diff: %d\n",
i+1, j/*, res[i], exp[i] */ );
}
}
if (tests_failed == 0) {
printf(
"%3d tests completed. %d tests PASSED. %d tests failed.\n",
n, tests_passed, tests_failed);
} else {
printf("%3d tests completed. %d tests passed. %d tests FAILED.\n",
n, tests_passed, tests_failed);
}
}
% pgfortran -fast bind.f90 bindc.c -o bind.out
bind.f90:
bindc.c:
% bind.out
28 tests completed. 28 tests PASSED. 0 tests failed.
4 tests completed. 4 tests PASSED. 0 tests failed.
Hope this helps,
Mat
Thanks Mat, appreciate that.
One question: how do I know the list of all C types that PGI Fortran currently supports with an interoperable type and kind parameter.
E.g.: I want to known the Fortran interoperable type with uint64_t in C. The book Fortran 95/2003 only mention int64_t.
Tuan
Hi Tuan,
E.g.: I want to known the Fortran interoperable type with uint64_t in C. The book Fortran 95/2003 only mention int64_t.
We support the standard which does not include unsigned types. You’ll need to use “C_INT64_T”. Though, this should be ok given how big of an integer you’d need to overflow into the negative values.
Thanks, Mat.
Tuan