So here is the fortran90 with C problem

This 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…]

Viewed 6525 times by 1221 viewers

Facebooktwittergoogle_plusredditpinterestlinkedinmail