ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I created a shared library with my most used mathematical functions using fortran 90. I intended to make my life easier, since I thought I could call the shared functions as simple as I call an intrinsic function like sin(x) or cos(x). However, I noted the functions in the shared library are treated as EXTERNAL functions. At this point my life became hard, because I have to interface my shared functions all the time. Is there a way to overcome this problem using fortran 90? Does this problem appear when using fortran 95?
Using Fortran 90/95 you can either write a library using module interfaces or just simple functions. I think it all depends on how did you wrote the function library and how did you compile/link it. Consider the following (very simplified) example. I am using the Intel fortran compiler on this machine:
Code:
$ ls
my_sum.f90 test.f90
$ cat my_sum.f90
FUNCTION my_sum(x,y)
REAL:: my_sum
REAL:: x, y
WRITE(*,*) 'x = ', x
WRITE(*,*) 'y = ', y
my_sum = x + y
END
$ ifort -c my_sum.f90
$ ls
my_sum.f90 my_sum.o test.f90
$ ld -o libtest.so.1 -dy -G -h libtest.so.1 *.o
$ ls
libtest.so.1 my_sum.f90 my_sum.o test.f90
$ ln -s libtest.so.1 libtest.so
$ ls
libtest.so libtest.so.1 my_sum.f90 my_sum.o test.f90
$ cat test.f90
PROGRAM test
REAL:: a, b, my_sum
READ(*,*) a
READ(*,*) b
R = my_sum(a,b)
WRITE(*,*) 'my_sum = ',R
END PROGRAM test
$ ifort -L. test.f90 -ltest
$ ls
a.out libtest.so libtest.so.1 my_sum.f90 my_sum.o test.f90
$ export LD_LIBRARY_PATH=$(pwd):${LD_LIBRARY_PATH}
$ echo $LD_LIBRARY_PATH
/home/colucix/test:/opt/intel/fc/10.1.015/lib:/opt/intel/cc/10.1.015/lib
$ ldd a.out
linux-gate.so.1 => (0x0041e000)
libtest.so.1 => /home/colucix/test/libtest.so.1 (0x00475000)
libm.so.6 => /lib/libm.so.6 (0x004e3000)
libc.so.6 => /lib/libc.so.6 (0x00111000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x002da000)
libdl.so.2 => /lib/libdl.so.2 (0x0050c000)
/lib/ld-linux.so.2 (0x00380000)
$ ./a.out
6
9
x = 6.000000
y = 9.000000
my_sum = 15.00000
$
Ok, I realized. But, suppose instead of my_sum.f90 I have a function
getsize(X) in a separated file:
Code:
function getsize(X)
implicit none
integer :: getsize
real, dimension (:) :: X
getsize=size(X)
end function getsize
In this case I need to interface the function getsize(X) in the main code:
Code:
program main
implicit none
real, dimension (10) :: A
! Interfacing the function getsize
interface
function getsize(X)
implicit none
integer :: getsize
real, dimension (:) :: X
end function getsize
end interface
write(*,*) getsize(A)
end program main
otherwise I'll get an error. That is the problem, I think it is not so practical to interface a shared function all the time.
You said it is possible write a library using module interfaces. I tried to do that, but it did not work. Suppose instead of the code above I have (in a separated file)
Code:
module mysize
contains
function getsize(X)
implicit none
integer :: getsize
real, dimension (:) :: X
getsize=size(X)
end function getsize
end module mysize
and as a main program
Code:
program main
use mysize
implicit none
real, dimension (10) :: A
write(*,*) getsize(A)
end program main
How can I proceed?
Thanks a lot!
Quote:
Originally Posted by colucix
Using Fortran 90/95 you can either write a library using module interfaces or just simple functions. I think it all depends on how did you wrote the function library and how did you compile/link it. Consider the following (very simplified) example. I am using the Intel fortran compiler on this machine:
Code:
$ ls
my_sum.f90 test.f90
$ cat my_sum.f90
FUNCTION my_sum(x,y)
REAL:: my_sum
REAL:: x, y
WRITE(*,*) 'x = ', x
WRITE(*,*) 'y = ', y
my_sum = x + y
END
$ ifort -c my_sum.f90
$ ls
my_sum.f90 my_sum.o test.f90
$ ld -o libtest.so.1 -dy -G -h libtest.so.1 *.o
$ ls
libtest.so.1 my_sum.f90 my_sum.o test.f90
$ ln -s libtest.so.1 libtest.so
$ ls
libtest.so libtest.so.1 my_sum.f90 my_sum.o test.f90
$ cat test.f90
PROGRAM test
REAL:: a, b, my_sum
READ(*,*) a
READ(*,*) b
R = my_sum(a,b)
WRITE(*,*) 'my_sum = ',R
END PROGRAM test
$ ifort -L. test.f90 -ltest
$ ls
a.out libtest.so libtest.so.1 my_sum.f90 my_sum.o test.f90
$ export LD_LIBRARY_PATH=$(pwd):${LD_LIBRARY_PATH}
$ echo $LD_LIBRARY_PATH
/home/colucix/test:/opt/intel/fc/10.1.015/lib:/opt/intel/cc/10.1.015/lib
$ ldd a.out
linux-gate.so.1 => (0x0041e000)
libtest.so.1 => /home/colucix/test/libtest.so.1 (0x00475000)
libm.so.6 => /lib/libm.so.6 (0x004e3000)
libc.so.6 => /lib/libc.so.6 (0x00111000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x002da000)
libdl.so.2 => /lib/libdl.so.2 (0x0050c000)
/lib/ld-linux.so.2 (0x00380000)
$ ./a.out
6
9
x = 6.000000
y = 9.000000
my_sum = 15.00000
$
Last edited by Gamma_User; 01-23-2009 at 02:18 PM.
Reason: TYPING ERROR
Your last example works for me. Here is an excerpt from Stephen Chapman's "FORTRAN 95/2003 for scientist and engineers" (don't waste time to look for it in the web... I have the book)
Quote:
The easiest way to create an explicit interface is to place procedures in a module, and then use that module in the calling program unit. Any procedures placed in a module will always have an explicit interface.
So I just tried the code you provided and it works in the following way:
Code:
$ cat mysize.f90
module mysize
contains
function getsize(X)
implicit none
integer :: getsize
real, dimension (:) :: X
getsize=size(X)
end function getsize
end module mysize
$ ifort -c mysize.f90
$ ld -o libtest.so.1 -dy -G -h libtest.so.1 *.o
$ ln -s libtest.so.1 libtest.so
$ cat main.f90
program main
use mysize
implicit none
real, dimension (10) :: A
write(*,*) getsize(A)
end program main
$ ifort -L. main.f90 -ltest
$ ls
a.out libtest.so libtest.so.1 main.f90 mysize.f90 mysize.mod mysize.o
$ export LD_LIBRARY_PATH=$(pwd):${LD_LIBRARY_PATH}
$ ./a.out
10
Perhaps the program worked because the mysize.mod and mysize.o files were in the directory. Try to remove them before using the command
Code:
ifort -L. main.f90 -ltest
Look at what happened in my computer:
Code:
hoggar%~/fortran/code ls
mysize.f90 uselib.f90
hoggar%~/fortran/code cat mysize.f90
module mysize
contains
function getsize(X)
implicit none
integer :: getsize
real, dimension (:) :: X
getsize=size(X)
end function getsize
end module mysize
hoggar%~/fortran/code cat uselib.f90
program main
use mysize
implicit none
real, dimension (10) :: A
write(*,*) getsize(A)
end program main
hoggar%~/fortran/code gfortran -c mysize.f90
hoggar%~/fortran/code ld -o libtest.so.1 -dy -G -h libtest.so.1 *.o
hoggar%~/fortran/code ln -s libtest.so.1 libtest.so
hoggar%~/fortran/code rm *.mod *.o
hoggar%~/fortran/code ls
libtest.so libtest.so.1 mysize.f90 uselib.f90
hoggar%~/fortran/code gfortran -L. uselib.f90 -ltest
uselib.f90:2.12:
use mysize
1
Fatal Error: Can't open module file 'mysize.mod' for reading at (1)
Thank you!
Quote:
Originally Posted by colucix
Your last example works for me. Here is an excerpt from Stephen Chapman's "FORTRAN 95/2003 for scientist and engineers" (don't waste time to look for it in the web... I have the book)
So I just tried the code you provided and it works in the following way:
Code:
$ cat mysize.f90
module mysize
contains
function getsize(X)
implicit none
integer :: getsize
real, dimension (:) :: X
getsize=size(X)
end function getsize
end module mysize
$ ifort -c mysize.f90
$ ld -o libtest.so.1 -dy -G -h libtest.so.1 *.o
$ ln -s libtest.so.1 libtest.so
$ cat main.f90
program main
use mysize
implicit none
real, dimension (10) :: A
write(*,*) getsize(A)
end program main
$ ifort -L. main.f90 -ltest
$ ls
a.out libtest.so libtest.so.1 main.f90 mysize.f90 mysize.mod mysize.o
$ export LD_LIBRARY_PATH=$(pwd):${LD_LIBRARY_PATH}
$ ./a.out
10
Last edited by Gamma_User; 01-26-2009 at 07:41 AM.
Reason: grammatical error
It works for me. But...
1) you have to preserve the mysize.mod and put it in some Include path, since it is used during the compilation of the main program
2) you have to tell to the system where to find the shared library, that is change the LD_LIBRARY_PATH environment variable accordingly OR use ldconfig to add the directory containing the libraries to the cache of the shared objects.
This equals to provide a devel package, that is: if you want to share with others the newly created libraries you have to provide both the libs and the includes. The library will be enough for already compiled executables linking against it. In addition the .mod will be necessary to develop and compile new applications!
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.