So here is the fortran90 with C problem
By joe
- 3 minutes read - 484 wordsThis is the example I concocted to help demonstrate the problem and help me learn how to solve it. The problem is, I solved this … without any fancy interface blocks or anything strange like that. Go figure.
The makefile
<code>
CC = icc
FC = ifort
LD = ifort
CFLAGS = -g
FFLAGS = -g
LFLAGS = -g
all: test.exe
test.exe: test_f.o test_c.o
$(LD) $(LFLAGS) test_f.o test_c.o -o test.exe
test_f.o: test.f90
$(FC) $(FFLAGS) -c $< -o test_f.o
test_c.o: test.c
$(CC) $(FFLAGS) -c $< -o test_c.o
clean:
rm -f *.o *.exe
</code>
the test.f90 code:
<code>
program test
integer, allocatable, dimension(:,:) :: a
integer :: b
integer :: n,m,i,j
real, allocatable, dimension(:,:) :: c
! -- allocate a and c as 10x10 arrays, and fill with sequential integers
allocate(a(10,10))
allocate(c(10,10))
do i=1,10
do j=1,10
a(i,j)=10*(i-1)+j
c(i,j)=dble(10*(i-1)+j)
enddo
enddo
n=10
m=10
print *,'In test.f90: printing out 1 column of a and then c'
print *,'a:'
do j=1,10
print *,'a(1,',j,') = ',a(1,j)
enddo
print *, ' '
print *,'c:'
do j=1,10
print *,'c(1,',j,') = ',c(1,j)
enddo
call test_c(n,m,a,c)
end program
</code>
the test.c code:
<code>
#include <stdio.h>
void test_c_(
int *n,
int *m,
int *a,
float *c
)
{
int i,j;
printf("in test.c: n=%i, m=%i, a=%x, c=%x\n",*n,*m,a,c);
for(i=0;i<*m;i++)
{
printf("a(%i,0)=%i\n",i,*(a+ (*m)*i+0));
}
for(i=0;i<*m;i++)
{
printf("c(%i,0)=%f\n",i,*(c+ (*m)*i+0));
}
return;
}
</code>
What is of interest is that Fortran includes metadata in its internal symbol tables that C doesn’t have access to. So you can’t write the C arrays as a[i][j], as this symbol metadata never traversed the language barrier. You have to do pointer arithmetic. Notice how it is done.
<code>
a[i][j] -> *(a + j * DIMENSION_ALONG_J + i)
</code>
which is equivalent to a(j-1,i-1) in Fortran90. Nice little Rosetta stone we have here :) When you run the code, this is what you get
~/testcase$ ./test.exe
In test.f90: printing out 1 column of a and then c
a:
a(1, 1 ) = 1
a(1, 2 ) = 2
a(1, 3 ) = 3
a(1, 4 ) = 4
a(1, 5 ) = 5
a(1, 6 ) = 6
a(1, 7 ) = 7
a(1, 8 ) = 8
a(1, 9 ) = 9
a(1, 10 ) = 10
c:
c(1, 1 ) = 1.000000
c(1, 2 ) = 2.000000
c(1, 3 ) = 3.000000
c(1, 4 ) = 4.000000
c(1, 5 ) = 5.000000
c(1, 6 ) = 6.000000
c(1, 7 ) = 7.000000
c(1, 8 ) = 8.000000
c(1, 9 ) = 9.000000
c(1, 10 ) = 10.00000
in test.c: n=10, m=10, a=129a030, c=129a1d0
a(0,0)=1
a(1,0)=2
a(2,0)=3
a(3,0)=4
a(4,0)=5
a(5,0)=6
a(6,0)=7
a(7,0)=8
a(8,0)=9
a(9,0)=10
c(0,0)=1.000000
c(1,0)=2.000000
c(2,0)=3.000000
c(3,0)=4.000000
c(4,0)=5.000000
c(5,0)=6.000000
c(6,0)=7.000000
c(7,0)=8.000000
c(8,0)=9.000000
c(9,0)=10.000000
So it works. Without an interface block. And indexing is basically correct. The hex address pointers appear to be valid. Now how to translate this to the code we are having trouble with … [updated … fixed my indexing errors…]