burow@cernvax.cern.ch (burkhard burow) (01/29/91)
I'm calling FORTRAN routines from C routines. The FORTRAN manual tells me how to pass, among other kinds of arguments, strings and arrays of numbers. But it doesn't tell me: QQQQQQQ: How do I pass an array of strings? There are many best guesses to try out, but I was hoping a netter could give me the answer. thanks INTERNET: burow%13313.hepnet@csa3.lbl.gov burkhard
merritt@iris613.gsfc.nasa.gov (John H Merritt) (01/29/91)
In article <3966@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >I'm calling FORTRAN routines from C routines. The FORTRAN manual tells me how Actually, the manual is not 100% clear on this. It is not clear on where the extra arguments (string lengths) are placed in the argument list when Fortran compiles. The constants string_lengths are placed LAST in the argument list and in the order that the strings appear; one for each string. >to pass, among other kinds of arguments, strings and arrays of numbers. But it >doesn't tell me: > >QQQQQQQ: How do I pass an array of strings? This is a tricky problem. For each array that you pass you must specify the string length as a constant and place it at the end of the argument list. If you have more than one string array passed, then list the constant lengths sequentially, and in the order that the arrays appear, at the end of the parameter list. You have to be conscience about setting up the C string arrays. For one thing they must not contain any unexpected NULL characters. Remember the storage is sequential. Here is an example of a FAILING program, followed by one that performs correctly. - cut Fortran subroutine (not changed for both FAILING and Working C mains) - subroutine t(name, n2, a, b, c) character *(*) name(4), n2(3) print*,'len(name(1)) =',len(name(1)) print*,'len(name(2)) =',len(name(2)) print*,'len(name(3)) =',len(name(3)) print*,'len(name(4)) =',len(name(4)) print*,'len(n2(1)) =',len(n2(1)) print*,'len(n2(2)) =',len(n2(2)) print*,'len(n2(3)) =',len(n2(3)) print*,'a',a print*,'b',b print*,'c',c print*,'name(1) =',name(1) print*,'name(2) =',name(2) print*,'name(3) =',name(3) print*,'name(4) =',name(4) print*,'n2(1) =',n2(1) print*,'n2(2) =',n2(2) print*,'n2(3) =',n2(3) return end - end cut - ---- cut C main for the FAILING program ---- main() { static char str[4][2] = {"1", "2", "3", "4"}; static char s2[3][6] = {"55555", "66666","77777"}; float a = 10.0; float b = 20.0; float c = 30.0; t_(str, s2, &a, &b, &c, strlen(str[0]),strlen(s2[0])); } ---- end cut C main for the FAILING program ---- When running this example you will see that the lengths for each string array are passed correctly, however on output the printed characters show the NULL's that are stored. Note: that the C character declarations have space for the terminating NULL characters. So the solution is to load the C arrays with exactly the characters you want and exactly specify the strings lengths yourself. I.e., you cannot use strlen because it relies on the NULL character to determine string lengths. ---- cut C main for the WORKING program ---- main() { char str[4][1]; char s2[3][5]; float a = 10.0; float b = 20.0; float c = 30.0; strncpy(str[0], "1", 1); strncpy(str[1], "2", 1); strncpy(str[2], "3", 1); strncpy(str[3], "4", 1); strncpy(s2[0], "55555", 5); strncpy(s2[1], "66666", 5); strncpy(s2[2], "77777", 5); t_(str, s2, &a, &b, &c, 1, 5); } ---- end cut C main for the WORKING program ---- Oh, now we are happy. John H. Merritt --> merritt@iris613.gsfc.nasa.gov Applied Research Corporation at NASA/GSFC "Yesterday I knew nothing, today I know that."