Prev: non printing characters
Next: Fortran problem
From: Tobias Burnus on 8 Jul 2010 03:36 On 07/08/2010 12:55 AM, Erik Toussaint wrote: > On 7-7-2010 23:53, Uno wrote: >> Now, the linker is complaining about not finding atan. If it were C, I >> would think to include math.h, but that's not relevant here. I tried >> adding -D_GNU_SOURCE to no avail, so I'm stuck again :-( >> >> $ gfortran -c -D_GNU_SOURCE -Wall -Wextra f_pi2.f90 -o fortranlib.o >> $ gcc fortranlib.o -std=c99 -Wall -Wextra c_pi2.c -o out >> fortranlib.o: In function `myArctan': >> f_pi2.f90:(.text+0x19): undefined reference to `atan' >> collect2: ld returned 1 exit status > > I think this happens because you invoke the linker as gcc. When invoked > as gfortran it automatically includes the fortran libraries, which > contain the code for the intrinsic functions. Or pass -lm (= libm, the math library), which is not really a gfortran library. If the symbol starts with __gfortran_... then you need gfortran's run-time library via -lgfortran. But unless you mix C++ (which needs -lstdc++) with Fortran, using "gfortran" for the linkage is the easiest. Tobias
From: Uno on 8 Jul 2010 15:03 Tobias Burnus wrote: > On 07/08/2010 12:55 AM, Erik Toussaint wrote: >> On 7-7-2010 23:53, Uno wrote: >>> Now, the linker is complaining about not finding atan. If it were C, I >>> would think to include math.h, but that's not relevant here. I tried >>> adding -D_GNU_SOURCE to no avail, so I'm stuck again :-( >>> >>> $ gfortran -c -D_GNU_SOURCE -Wall -Wextra f_pi2.f90 -o fortranlib.o >>> $ gcc fortranlib.o -std=c99 -Wall -Wextra c_pi2.c -o out >>> fortranlib.o: In function `myArctan': >>> f_pi2.f90:(.text+0x19): undefined reference to `atan' >>> collect2: ld returned 1 exit status >> I think this happens because you invoke the linker as gcc. When invoked >> as gfortran it automatically includes the fortran libraries, which >> contain the code for the intrinsic functions. > > Or pass -lm (= libm, the math library), which is not really a gfortran > library. If the symbol starts with __gfortran_... then you need > gfortran's run-time library via -lgfortran. > > But unless you mix C++ (which needs -lstdc++) with Fortran, using > "gfortran" for the linkage is the easiest. $ gcc -c -std=c99 -Wall -Wextra c_pi2.c -o clib.o $ gfortran clib.o fortranlib.o -o out $ gcc clib.o fortranlib.o -o out2 fortranlib.o: In function `myArctan': f_pi2.f90:(.text+0x19): undefined reference to `atan' collect2: ld returned 1 exit status $ gcc clib.o fortranlib.o -lm -o out2 $ ./out2 d in C is 0.785398 myarctan(1.000000e+00) = 7.853982e-01 $ ./out d in C is 0.785398 myarctan(1.000000e+00) = 7.853982e-01 $ Alright, so this is looking better. It seems to work a lot better when you compile the translation units separately, then stich them up at the end, as user1 writes. I seem to forget this lesson in the interstices. I've got more to do with this, but now have to go out and beat the brush for some legal tender. Cheers, -- Uno
From: Uno on 9 Jul 2010 16:01 m_b_metcalf wrote: > On Jul 7, 6:29 am, Uno <merrilljen...(a)q.com> wrote: >> q2) If this calculation is done in a posix-compliant environment, are >> the widths of C's double and fortran's default real related? >> > > Does the Table 14.1 in MR&C, p. 250, provide you with the > information you're looking for? Somewhat. Can a person think about a single precision real as being a float and double precision being a double without being too wrong? > >> q3) Why does the MR&C development need the interface listed in figure >> 14.3 *and* the interface lsited in 14.4? >> > Fig. 14.3 is related to Fortran calling C. It's 14.4 you want. Alright. I think I need to pinch myself, because I think I got this: $ gcc -Wall -Wextra -lm c_mm1.c -o out $ gfortran -c -Wall -Wextra f_mm1.f03 -o pass.o $ gcc -c -Wall -Wextra -lm c_mm1.c -o caller.o $ gcc pass.o caller.o -lgfortran -o out $ ./out vector[0] is 0.785398 vector[1] is 1.107149 vector[2] is 1.249046 vector[3] is 1.325818 vector[4] is 1.373401 0.78539819 1.1071488 1.2490457 1.3258177 1.3734008 $ cat c_mm1.c #include <stdio.h> #include <math.h> #define size 5 struct pass { int lenc; float* c; }; void simulation( struct pass* arrays ); int main() { float vector[size]; int i; struct pass arrays; for (i=0; i<size; ++i) { vector[i] = atan(1 + i); printf("vector[%d] is %f\n", i, vector[i]); } arrays.lenc = size; arrays.c = &vector[0]; simulation( &arrays ); return 0; } // gcc -c -Wall -Wextra -lm c_mm1.c -o caller.o // gcc pass.o caller.o -lgfortran -o out $ cat f_mm1.f03 subroutine simulation(arrays) bind(c) use iso_c_binding type, bind(c) :: pass integer (c_int) :: lenc type (c_ptr) :: c end type pass type (pass), intent(in) :: arrays real (c_float), pointer :: c_array(:) ! associate c_array with an array allocated in C call c_f_pointer( arrays%c, c_array, (/arrays%lenc/) ) print *, c_array end subroutine simulation ! gfortran -c -Wall -Wextra f_mm1.f03 -o pass.o $ How would I have to alter pass to accomodate arrays of higher rank? -- Uno
From: Richard Maine on 9 Jul 2010 17:46 Uno <merrilljensen(a)q.com> wrote: > m_b_metcalf wrote: > > On Jul 7, 6:29 am, Uno <merrilljen...(a)q.com> wrote: > >> q2) If this calculation is done in a posix-compliant environment, are > >> the widths of C's double and fortran's default real related? > >> > > > > Does the Table 14.1 in MR&C, p. 250, provide you with the > > information you're looking for? > > Somewhat. Can a person think about a single precision real as being a > float and double precision being a double without being too wrong? Often, even usually, but not always. If that were always the case, then the committee wouldn't have gone to the bother of defining C_float and C_double. Since those exist specifically for the purpose, why not use them and be always right instead of avoiding them and being sometimes wrong? It isn't as though there is any big difficulty in using them. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain
From: Uno on 9 Jul 2010 22:50
On 7/9/2010 1:01 PM, Uno wrote: > m_b_metcalf wrote: >> On Jul 7, 6:29 am, Uno <merrilljen...(a)q.com> wrote: > Alright. I think I need to pinch myself, because I think I got this: > > $ gcc -Wall -Wextra -lm c_mm1.c -o out > $ gfortran -c -Wall -Wextra f_mm1.f03 -o pass.o > $ gcc -c -Wall -Wextra -lm c_mm1.c -o caller.o > $ gcc pass.o caller.o -lgfortran -o out > > $ ./out > vector[0] is 0.785398 > vector[1] is 1.107149 > vector[2] is 1.249046 > vector[3] is 1.325818 > vector[4] is 1.373401 > 0.78539819 1.1071488 1.2490457 1.3258177 1.3734008 > $ cat c_mm1.c > #include <stdio.h> > #include <math.h> > #define size 5 > struct pass { > int lenc; > float* c; > > }; > void simulation( struct pass* arrays ); > int main() > { > > float vector[size]; > int i; > struct pass arrays; > > for (i=0; i<size; ++i) > { > vector[i] = atan(1 + i); > printf("vector[%d] is %f\n", i, vector[i]); > } > > arrays.lenc = size; > arrays.c = &vector[0]; > > simulation( &arrays ); > return 0; > } > > // gcc -c -Wall -Wextra -lm c_mm1.c -o caller.o > // gcc pass.o caller.o -lgfortran -o out > $ cat f_mm1.f03 > > subroutine simulation(arrays) bind(c) > use iso_c_binding > type, bind(c) :: pass > integer (c_int) :: lenc > type (c_ptr) :: c > end type pass > type (pass), intent(in) :: arrays > real (c_float), pointer :: c_array(:) > > ! associate c_array with an array allocated in C > call c_f_pointer( arrays%c, c_array, (/arrays%lenc/) ) > print *, c_array > end subroutine simulation > ! gfortran -c -Wall -Wextra f_mm1.f03 -o pass.o > $ > > How would I have to alter pass to accomodate arrays of higher rank? Let me be more specific here. The original pass has 2 more variables, presumably to deal with a 2-d array: subroutine simulation(arrays) bind(c) use iso_c_binding type, bind(c) :: pass integer (c_int) :: lenc, lenf type (c_ptr) :: c, f end type pass type (pass), intent(in) :: arrays real (c_float), pointer :: c_array(:) ! associate c_array with an array allocated in C call c_f_pointer( arrays%c, c_array, (/arrays%lenc/) ) print *, c_array end subroutine simulation The c side would then be #include <stdio.h> #include <math.h> #define size1 5 #define size2 7 struct pass { int lenc, int lenf; float* c, f; }; .... To populate this data structure, I would then loop over both dimensions (not shown): for (i=0; i<size; ++i) { vector[i] = atan(1 + i); printf("vector[%d] is %f\n", i, vector[i]); } The analog of this would be something like: arrays.lenc = size1; arrays.lenf = size2; But here's the one I am clueless on. arrays.c = &vector[0]; arrays.f = ??????; Thanks for your comment, -- Uno |