From: Tobias Burnus on
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
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
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
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
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
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4
Prev: non printing characters
Next: Fortran problem