mixing C library in Fortran

recently LK send me an query from customer about calling C library in Fortran

question is the following

We have a f90 code, which uses rand, irand, srand fnctions a lot. That code works fine on other platform, e.g., SP, but on the Sun workstation, the code cannot be compiled because of no_found srand. Enclosed below please find a small example that I created just for demonstrating the problem. f90 -xpp=cpp use_srand.f90 -lc -lm gives this error: Undefined first referenced symbol in file srand_ use_srand.o ld: fatal: Symbol referencing errors. No output written to a.out Is there any tricky stuff in calling C library?

PROGRAM use_srand
INTEGER\*4 :: SEED(2),time,current_time,irand
EXTERNAL srand, irand
current_time=time()
print\*,' Current_time ', current_time
call srand(current_time)
print\*,' Current_time ', current_time
SEED(1)=irand(current_time)
SEED(2)=irand(current_time+1)
print\*,' SEED(1) ', SEED(1), ' SEED(2) ', SEED(2)
stop
end

Since I donot work with codes everyday so I look it up on http://docs.sun.com/ Sun have many different version of compiler, but in each version there are instruction about calling C library in Fortran

I also have two internal machines to test the codes, one has FD7 compiler one has SS9

FD7 Fortran reference manul chapter11

11.1.4 Underscores in Routine Names
The Fortran compiler normally appends an underscore (_) to the names of subprograms appearing both at entry point definition and in calls. This convention differs from C procedures or external variables with the same user-assigned name. Almost all Fortran library procedure names have double leading underscores to reduce clashes with user-assigned subroutine names.
There are three usual solutions to the underscore problem:

  • In the C function, change the name of the function by appending an underscore to that name
  • Use the C() pragma to tell the Fortran compiler to omit those trailing underscores.
  • Use the f95 -ext_names option to compile references to external names without underscores.
Use only one of these solutions.

The examples in this chapter could use the C() compiler pragma to avoid underscores. The C() pragma directive takes the names of external functions as arguments. It specifies that these functions are written in the C language, so the Fortran compiler does not append an underscore as it ordinarily does with external names. The C()directive for a particular function must appear before the first reference to that function. It must also appear in each subprogram that contains such a reference. The conventional usage is:
EXTERNAL ABC, XYZ !$PRAGMA C( ABC, XYZ )
If you use this pragma, the C function does not need an underscore appended to the function name. (Pragma directives are described in the Fortran User's Guide

I make the following change


PROGRAM use_srand
INTEGER\*4 :: SEED(2),time,current_time,irand
EXTERNAL srand , irand
!$PRAGMA C(srand)
current_time=time()
print\*,' Current_time ', current_time
call srand(current_time)
print\*,' Current_time ', current_time
SEED(1)=irand(current_time)
SEED(2)=irand(current_time+1)
print\*,' SEED(1) ', SEED(1), ' SEED(2) ', SEED(2)
stop
end

  • compile f90 linda.f90
  • run ./a.out
    Current_time 1103814443
    Current_time 1103814443
    SEED(1) 340799264 SEED(2) 2018393530

For SS9 , the docs said the followings:
There are three usual solutions to the underscore problem:

  • In the C function, change the name of the function by appending an underscore to that name.
  • Use the BIND(C) attribute declaration to indicate that an external function is a C language function.
  • Use the f95 -ext_names option to compile references to external names without underscores.
Use only one of these solutions.
The examples in this chapter could use the BIND(C) attribute declaration to avoid underscores. BIND(C) declares the C external functions that can be called from Fortran, and the Fortran routines that can be called from C as arguments. The Fortran compiler does not append an underscore as it ordinarily does with external names. The BIND(C) must appear in each subprogram that contains such a reference. The conventional usage is:
FUNCTION ABC EXTERNAL XYZ
BIND(C) ABC, XYZ
Here the user has specified not only that XYZ is an external C function, but that the Fortran caller, ABC, should be callable from a C function. If you use BIND(C), the C function does not need an underscore appended to the function name
so I make the similar change and it compile and run, just like the FD7 case.
PROGRAM use_srand
INTEGER\*4 :: SEED(2),time,current_time,irand
EXTERNAL srand , irand
BIND(srand)
current_time=time()
print\*,' Current_time ', current_time
call srand(current_time)
print\*,' Current_time ', current_time
SEED(1)=irand(current_time)
SEED(2)=irand(current_time+1)
print\*,' SEED(1) ', SEED(1), ' SEED(2) ', SEED(2)
stop
end
Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

hstsao

Search

Top Tags
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today