mlzerkle@athena.mit.edu (Michael L Zerkle) (11/10/90)
I am trying to develop C functions to allocate and deallocate arrays for use in a FORTRAN progam that would run on a number of different UNIX boxes (DEC VS3100, Apollo, SGI 4D/210, etc.). The C functions I have written appear to allocate the double array correctly, but either it does not pass it back the the FORTRAN program correctly, or the FORTRAN program is not accepting the pointer/array it is returning. Does anyone out there have any experience with problems of this sort, or know what I am doing wrong? Any suggestions? Basic info: SGI 4D/210VGXB f77 compiler ANSI C compiler same problem on other UNIX systems. Thanks in advance for any help. Mike Zerkle mlzerkle@athena.mit.edu ******************** * Fortran Code ... * ******************** program testgetm real*8 a(1) integer*4 maxa,bytesa,i external getmd,freemd c maxa=5 bytesa=8 c c Write Initial location. c write(6,'(a)') 'Initial address' write(6,*) loc(a),maxa,bytesa c c Allocate real*8 array. c call getmd(a,maxa) c c Write addresses c write(6,'(a)') 'Final address' write(6,*) loc(a),maxa,bytesa c c Work on array c write(6,'(a)') 'REAL*8 array ' if (loc(a).ne.0) then do 10 i=1,maxa c a(i)= 1.0d+0*i write(6,*) i, a(i) 10 continue else write(6,'(a)') ' Unable to allocate r*8 array a' endif c c Free arrays. c if (loc(a).ne.0) call freemd(a) c stop end ************** * C Code ... * ************** #include <stdlib.h> void getmd_(double *array, int *nelem) { printf("org array addr = %ld\n",array); array = (double *) calloc((size_t) *nelem, (size_t) sizeof(double)); printf("new array addr = %ld\n",array); } void freemd_(double *array) { free((void *) array); } ********************* * Sample output ... * ********************* Initial address 29996 5 8 org array addr = 29996 new array addr = 54272 Final address 29996 5 8 REAL*8 array 1 0. 2 0. 3 0. 4 1.1840974637956d+30 5 5.2810833895564d-20 Keywords:
bron@bronze.wpd.sgi.com (Bron Campbell Nelson) (11/13/90)
In article <1990Nov9.212649.27564@athena.mit.edu>, mlzerkle@athena.mit.edu (Michael L Zerkle) writes: > I am trying to develop C functions to allocate and deallocate arrays > for use in a FORTRAN progam that would run on a number of different > UNIX boxes (DEC VS3100, Apollo, SGI 4D/210, etc.). The C functions > I have written appear to allocate the double array correctly, but > either it does not pass it back the the FORTRAN program correctly, or > the FORTRAN program is not accepting the pointer/array it is returning. > > Does anyone out there have any experience with problems of this sort, > or know what I am doing wrong? Any suggestions? > I'll skip over the error in the code and instead mention one way that you can do this using SGI Fortran. It relys on a couple of things: (1) Fortran array parameters are passed simply by passing the address (no funny array descriptors or dope vectors) (2) The VAX Fortran "%val" extension. These two assumptions are true with SGI Fortran, and are probably true on a number of other platforms. For instance, the following program will behave like one would hope: integer foo foo = malloc(1000*1000*4) call fill(%VAL(foo), 1000,1000) end subroutine fill(a,i,j) real a(i,j) do n1 = 1, 1000 do n2 = 1, 1000 a(n2,n1) = 0.0 enddo enddo return end Some versions of the SGI software do not define a Fortran interface to malloc. In such a case you'll also have to write the 1 line C routine int malloc_(size) int *size; { return (int) malloc(*size); } -- Bron Campbell Nelson bron@sgi.com or possibly ..!ames!sgi!bron These statements are my own, not those of Silicon Graphics.
calvin@dinkum.wpd.sgi.com (Calvin H. Vu) (11/13/90)
In <1990Nov9.212649.27564@athena.mit.edu> mlzerkle@athena.mit.edu (Michael L Zerkle) writes: | I am trying to develop C functions to allocate and deallocate arrays | for use in a FORTRAN progam that would run on a number of different | UNIX boxes (DEC VS3100, Apollo, SGI 4D/210, etc.). The C functions | I have written appear to allocate the double array correctly, but | either it does not pass it back the the FORTRAN program correctly, or | the FORTRAN program is not accepting the pointer/array it is returning. | | Does anyone out there have any experience with problems of this sort, | or know what I am doing wrong? Any suggestions? You cannot assign an address to an array at runtime to turn the array into a relocatable array. On SGI systems, the type POINTER is supported to allow you to do this (see the latest F77 Reference Manual on POINTER specification if you have one). For example: real*8 a(1) pointer (ptr, a) maxa = 5 C You have to use an assignment (or DATA statement) to give 'ptr' a value C since it doesn't have a storage allocated for it i.e. you cannot C use it as an actual argument and assign a value to it in the called C subroutine ptr = malloc(maxa*8) do i=1,maxa a(i) = i enddo end For systems which do not support POINTER type you can do the following trick: integer ptr, maxa maxa = 5 ptr = malloc(maxa*8) call malloc_array(%val(ptr)) !pass value of ptr to be used as address end subroutine malloc_array(a) dimension a(1) do i=1,maxa a(i) = i enddo return end The following is a modified version of your program which works on SGI systems (and DEC). program testgetm real*8 a(1) pointer (ptr, a) integer*4 maxa,bytesa,i c external getmd,freemd c maxa=5 bytesa=8 c c Write Initial location. c write(6,'(a)') 'Initial address' c write(6,*) ptr,maxa,bytesa c c Allocate real*8 array. c c call getmd(ptr,maxa) ptr = malloc(maxa*8) c c Write addresses c write(6,'(a)') 'Final address' c write(6,*) ptr,maxa,bytesa c c Work on array c write(6,'(a)') 'REAL*8 array ' if (ptr.ne.0) then do 10 i=1,maxa a(i)= 1.0d+0*i write(6,*) i, a(i) 10 continue else write(6,'(a)') ' Unable to allocate r*8 array a' endif c c Free arrays. c c if (loc(a).ne.0) call freemd(a) if (ptr.ne.0) call free(ptr) c stop end Hope it helps, - calvin -- ----------------------------------------------------------------------------- Calvin H. Vu | "We are each of us angels with only one Silicon Graphics Computer Systems | wing. And we can only fly embracing calvin@sgi.com (415) 962-3679 | each other."