Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28988 Discussions

f77 arpack in OS X calling from c++ with gcc

abryden
Beginner
416 Views
I am trying to call functions from the f77 version of arpack compiled with ifort from within a c++ program. I managed to get it to find the symbols properly but have been unable to get it to work without segfaulting (usually with an attempt to derefence a NULL pointer)

I have been able to get it to work with gfortran but for obvious reasons we would like to be able to use intel fortran. Currently the way I declare a function in my c++ code for calling is in an extern c block with the data types translated

for instance


subroutine dsaupd
& ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam,
& ipntr, workd, workl, lworkl, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ldv, lworkl, n, ncv, nev
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(11)
Double precision
& resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)


becomes


void dsaupd_(integer *ido, char *bmat, integer *n, char *which,
integer *nev, double *tol, double *resid,
integer *ncv, double *V, integer *ldv,
integer *iparam, integer *ipntr, double *workd,
double *workl, integer *lworkl, integer *info);


where integer and logical are typedefed to be a long int (i have also tried just int)

Is their a good concrete guide to taking an f77 function and calling it from c, the technique i used seems to work for gfortran but not ifort. I looked in the manual but I couldn't find a guide for the default calling conventions
0 Kudos
4 Replies
TimP
Honored Contributor III
416 Views
I'm surprised this worked with gfortran, as gfortran (to the best of my knowledge) uses the same convention of appending character string lengths to the argument list, when not using ISO C binding. There was no portable way of doing this in Fortran 77 or 90, although ifort and gfortran conform to the majority view on how to do it for linux.
In both ifort and gfortran, Fortran default integers match C int. They would match long int only in the 32-bit version. ISO C binding saves you from these dependencies.
0 Kudos
abryden
Beginner
416 Views
thanks for the reply.

I'm making a 32 bit application so I have to use 32 bit ifort(is their a big advantage to 64 bit? if so maybe I will work on making my application 64 bit) hence the long ints.

Where in the argument stack is the character string length and what type is it? Is it possible to set up the c call such that if I know the string length I can just pass it in as one of the parameters?

Also if I end up having to use the ISO C bindings will I have to do that for all my fortran suboutines that are called by the subroutine that I call from c or can I just modify the 2 ARPACK functions that I need to call from c and their subroutine calls will be fine?

thanks,

aaron
0 Kudos
TimP
Honored Contributor III
416 Views
The biggest advantage in going to 64 bits is to permit your application to use more memory. Usual performance advantage is in the 10% range, it's highly problem dependent.
If your arrays are too large for 32-bit subscripts (4GB for 32-bit data) you need 64-bit integer subscripts (kind=8 for gfortran or ifort), C_LONG or C_LONG_LONG.
The corresponding C and Fortran data types are shown in the "interoperability with C" section of ifort documentation. You will note that only C_LONG and C_SIZE_T change between 32- and 64-bit linux.
Unfortunately, the ISO C binding way of passing character strings (len > 1) is not shown in the document. By specifying C_CHAR you avoid the hidden extra character string length arguments which seem to have bitten you. A variable length string would likely have an explicit length added to the argument list on both sides, rather than being hidden on the Fortran side. An array of C_CHAR length 2 should interoperate with CHARACTER(len=2), although there was some confusion.
It should be possible, as you say, to specify C binding names just for the subroutines which are called from C.
0 Kudos
abryden
Beginner
416 Views
I got it to work. I'm posting this for anyone else that may be doing the same things.

If your ARPACK interface relies on dseupd and dsaupd you can just pass char pointers without array length arguments because the length of the array is specified in the subroutine definitions.

On OS X if you are using 32 bit ifort you have to pass in long ints for integers and logicals.

The reason I was getting the segfaults was not because I was mangling the stack but because I needed to upgrade to 10.1.012 on leopard.
0 Kudos
Reply