Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

gfortran to compile/link to DLL (win) and SO(linux)

742 views
Skip to first unread message

Alex van der Spek

unread,
Aug 15, 2012, 3:28:18 PM8/15/12
to
No experience at all with gfortran. I have relied on MS PowerStation 4 for
the last 15 years or so. With that compiler I could create a DLL (not SO
obviously) and have control over which routines are to be exported and which
not, the calling convention (C or pascal) and the passing by value or
passing by reference. An example is below:

FUNCTION FZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ)
*RESULT(IERR)
!MS$ATTRIBUTES DLLEXPORT :: FZAIRY
!MS$ATTRIBUTES STDCALL :: FZAIRY
!MS$ATTRIBUTES VALUE :: ZR, ZI, ID, KODE
!MS$ATTRIBUTES REFERENCE :: AIR, AII, NZ
DOUBLE PRECISION ZR, ZI, AIR, AII
INTEGER KODE, ID, NZ, IERR
CALL ZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ, IERR)
RETURN
END

Most of the time I have old F77 type FORTRAN. The call to ZAIRY is to a
netlib routine from Donald Amos. How would the equivalent look like for
gfortran? Can I compile/link to SO and DLL? Can I change the calling
convention (VB/VBA requires STDCALL, whereas R and Python require the C
calling convention). How do I tell gfortran only to export certain routines
and not export others?

Any help much appreciated!

Regards,
Alex van der Spek

Tobias Burnus

unread,
Aug 15, 2012, 4:24:36 PM8/15/12
to
Alex van der Spek wrpte:
> No experience at all with gfortran. I have relied on MS PowerStation 4
> for the last 15 years or so. With that compiler I could create a DLL
> (not SO obviously) and have control over which routines are to be
> exported and which not, the calling convention (C or pascal) and the
> passing by value or passing by reference. An example is below:
>
> FUNCTION FZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ)
> *RESULT(IERR)
> !MS$ATTRIBUTES DLLEXPORT :: FZAIRY
> !MS$ATTRIBUTES STDCALL :: FZAIRY
> !MS$ATTRIBUTES VALUE :: ZR, ZI, ID, KODE
> !MS$ATTRIBUTES REFERENCE :: AIR, AII, NZ
> DOUBLE PRECISION ZR, ZI, AIR, AII
> INTEGER KODE, ID, NZ, IERR
> CALL ZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ, IERR)
> RETURN
> END
>
> Most of the time I have old F77 type FORTRAN. The call to ZAIRY is to a
> netlib routine from Donald Amos. How would the equivalent look like for
> gfortran?

Well, DLLEXPORT and STDCALL are handled via "!GCC$" instead of "!MS$";
REFERENCE is the default.

VALUE and the naming of the function � as seen by the C program � is
handled in gfortran via Fortan 2004's C interoperability support.

Hence, the equivalent to your function should be something like:


function fzairy (zr, zi, id, kode, air, aii, nz) result(ierr) BIND(C)
!GCC$ attributes dllexport, stdcall :: fzairy
double precision, VALUE :: zr, zi
integer, VALUE :: id, kode
double precision :: air, aii
integer :: nz, ierr

CALL ZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ, IERR)
end function fzairy

should be equivalent.

BIND(C) and VALUE are standard Fortran 2003 features � and dllexport and
stdcall you already know.

See
http://gcc.gnu.org/onlinedocs/gfortran/Mixed_002dLanguage-Programming.html
The first section is about C interoperability between C and Fortran
using C Fortran 2003's C binding; the second section is about !GCC$.

(The naming of the function is handled via BIND(C, name="something"); on
32bit Windows, gfortran automatically adds a leading underscore for
CDECL and a tailing "@" followed by the number of bytes on the stack for
STDCALL. On 64bit Windows, I think basically everything uses CDECL.)

Tobias

James Van Buskirk

unread,
Aug 15, 2012, 6:41:32 PM8/15/12
to
"Tobias Burnus" <bur...@net-b.de> wrote in message
news:502C0584...@net-b.de...

> Alex van der Spek wrpte:

>> No experience at all with gfortran. I have relied on MS PowerStation 4
>> for the last 15 years or so. With that compiler I could create a DLL
>> (not SO obviously) and have control over which routines are to be
>> exported and which not, the calling convention (C or pascal) and the
>> passing by value or passing by reference. An example is below:

>> FUNCTION FZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ)
>> *RESULT(IERR)
>> !MS$ATTRIBUTES DLLEXPORT :: FZAIRY
>> !MS$ATTRIBUTES STDCALL :: FZAIRY
>> !MS$ATTRIBUTES VALUE :: ZR, ZI, ID, KODE
>> !MS$ATTRIBUTES REFERENCE :: AIR, AII, NZ
>> DOUBLE PRECISION ZR, ZI, AIR, AII
>> INTEGER KODE, ID, NZ, IERR
>> CALL ZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ, IERR)
>> RETURN
>> END

>> Most of the time I have old F77 type FORTRAN. The call to ZAIRY is to a
>> netlib routine from Donald Amos. How would the equivalent look like for
>> gfortran?

> Well, DLLEXPORT and STDCALL are handled via "!GCC$" instead of "!MS$";
> REFERENCE is the default.

> VALUE and the naming of the function � as seen by the C program � is
> handled in gfortran via Fortan 2004's C interoperability support.

> Hence, the equivalent to your function should be something like:

> function fzairy (zr, zi, id, kode, air, aii, nz) result(ierr) BIND(C)
> !GCC$ attributes dllexport, stdcall :: fzairy
> double precision, VALUE :: zr, zi
> integer, VALUE :: id, kode
> double precision :: air, aii
> integer :: nz, ierr

> CALL ZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ, IERR)
> end function fzairy

> should be equivalent.

> BIND(C) and VALUE are standard Fortran 2003 features � and dllexport and
> stdcall you already know.

> See
> http://gcc.gnu.org/onlinedocs/gfortran/Mixed_002dLanguage-Programming.html
> The first section is about C interoperability between C and Fortran using
> C Fortran 2003's C binding; the second section is about !GCC$.

> (The naming of the function is handled via BIND(C, name="something"); on
> 32bit Windows, gfortran automatically adds a leading underscore for CDECL
> and a tailing "@" followed by the number of bytes on the stack for
> STDCALL. On 64bit Windows, I think basically everything uses CDECL.)

For compiling I had to look up one of my old messages

https://groups.google.com/group/comp.lang.fortran/msg/8b1f01ce0a7b035c?hl=en

The way google has broken their interface you may not be able to use
this link, unfortunately. On Windows, the command line would be
(assuming the file was named fzairy.f90 and the *.dll will be
named fzairy.dll)

gfortran fzairy.f90 -shared -ofzairy.dll

Hopefully making a *.so file shouldn't be any more complicated
than that.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Tobias Burnus

unread,
Aug 16, 2012, 2:24:01 AM8/16/12
to
James Van Buskirk wrote:
> gfortran fzairy.f90 -shared -ofzairy.dll
>
> Hopefully making a *.so file shouldn't be any more complicated
> than that.

On Unix, besides the -shared you also need to specify the -fpic flag
when compiling.*

On the other hand, STDCALL and DLLIMPORT are not needed. It is better to
disabled those attributes, e.g. with conditional compilation, when
compiling for Linux. While DLLIMPORT is ignored, I am not completely
sure about STDCALL; if it isn't ignored, it will cause problem as the
arguments are popped twice from the stack. At least with 32bit Linux I
would be careful; I beliefe the 64 bit platform ABI doesn't specify
STDCALL and thus you should be safe.

(If you want to call the procedures which have a BIND(C) or VALUE from
Fortran, you need to have an explicit interface, e.g. by placing them
into a module. I think you don't want to call them from Fortran, but if
you do I recommend to browse some book about Fortran 90 (or later) on
the topic module, internal procedures and interface.)


Tobias

From the manual:

-fpic
Generate position-independent code (PIC) suitable for
use in a shared library, if supported for the target
machine. Such code accesses all constant addresses
through a global offset table (GOT). The dynamic
loader resolves the GOT entries when the program
starts (the dynamic loader is not part of GCC; it is
part of the operating system). If the GOT size for
the linked executable exceeds a machine-specific
maximum size, you get an error message from the linker
indicating that -fpic does not work; in that case,
recompile with -fPIC instead. (These maximums are 8k
on the SPARC and 32k on the m68k and RS/6000. The 386
has no such limit.)

Position-independent code requires special support,
and therefore works only on certain machines. For the
386, GCC supports PIC for System V but not for the Sun
386i. Code generated for the IBM RS/6000 is always
position-independent.
0 new messages