Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

Linking C/FORTRAN

connell
Beginner
2,528 Views

I have a C library that has been set up with a -iface:cvf type interface. I.e. if I compile the FORTRAN with -iface:cvf then it link correctly. Unfortunately in the FORTRAN I have calls to other C and FORTRAN librariesthat do not use the cvf calling convention.

From what I have read I need to set up an interface block with a CFV type compiler directive. I.e. call some routines with thecvf type convention. Something like

interface
subroutine gm_start_cad(igeofile,lugeo_in,isemod,split2)
c CDEC$ ATTRIBUTES CVF :: gm_start_cad
character*80 igeofile
integer lugeo_in, isemod
logical split2
end subroutine gm_start_cad
end interface

Unfortunately the compiler does not recognise the CVF option. I have tried various other combinations (DECORATE, ALIAS, STDCALL) but cannot get it to link. Does anyone know what set of directives I need to mimick the cvf convention? Or is there another way of doing this?

0 Kudos
21 Replies
Steven_L_Intel1
Employee
2,209 Views
There is not a CVF attribute, though there really should be. You also have the syntax for directives wrong. You'll need to use this instead:

!DEC$ ATTRIBUTES STDCALL,REFERENCE,DECORATE.,ALIAS:"GM_START_CAD" :: gm_start_cad


0 Kudos
connell
Beginner
2,209 Views

Thanks for the response - trying that directive I get

libgeolib.a(gm_util.o) : error LNK2019: unresolved external symbol _GM_START_CAD@16 referenced in function _GM_START

The argument list to gm_start_cad is (character,int, int, logical) If I nm -a the library is has an entry for _GM_START_CAD@20which is what I would expect with the extra int for the length of the string. It looks like the directives are not adding the length of the string to the argument list. Is there any way around this (apart from adding the argument myself)

0 Kudos
Steven_L_Intel1
Employee
2,209 Views
I don't see why the string length should have been ignored unless you also added a REFERENCE attribute for the string argument. However, I forgot an attribute for the routine - add MIXED_STR_LEN_ARG. I tested this and it worked for me.
0 Kudos
connell
Beginner
2,209 Views
I have added the MIXED_STR_LEN_ARGthe compiler complains - I think it may be past collum 72- is there a continuation method for compiler directives. My file is attached
0 Kudos
Steven_L_Intel1
Employee
2,209 Views
No, you can't continue directives, but you can add a second ATTRIBUTES directive on another line to add more attributes to the name.
0 Kudos
connell
Beginner
2,209 Views

I used -extend_source for the compiler option

Next question - do I need to add the string length after the character variable in the argument list? see below, If I do this the code crashes in calling the c routine.

subroutine gm_start_cad(igeofile,lugeo_in,isemod,split2)
character*(*) igeofile
logical split2
interface
subroutine gm_start_cad1(igeofile,li,lugeo_in,isemod,split2)
CDEC$ ATTRIBUTES DECORATE,STDCALL,MIXED_STR_LEN_ARG,ALIAS:'GM_START_CAD' :: gm_start_cad1
character*80 igeofile
integer lugeo_in, isemod
logical split2
end subroutine gm_start_cad1
end interface
write(6,*)' in interface routine igeofile =',igeofile
li = len(igeofile)
call gm_start_cad1(igeofile,li,lugeo_in,isemod,split2)
return
end

0 Kudos
Steven_L_Intel1
Employee
2,209 Views
You also need the REFERENCE attribute, though you haven't shown me what the C call looks like. Otherwise it won't accept the string properly. The lengrth should be passed by value immediately following the string address.
0 Kudos
connell
Beginner
2,209 Views

What syntrax is used in the compiler directive to specify the way of passing arguments? i.e. som by value, some by address.I have dug through the documentation - it says you can do it but I could find no example.

0 Kudos
connell
Beginner
2,209 Views

I think I have it going now - if I add REFERENCE then the string length is embeded automatically. I would still like to know how to specify reference/value for individual arguments as I will need this.

many thanks for the help!

0 Kudos
Steven_L_Intel1
Employee
2,209 Views
Follow each argument declaration with:

!DEC$ ATTRIBUTES REFERENCE :: argname
or
!DEC$ ATTRIBUTES VALUE :: argname

as appropriate.

I highly recommend a careful read of the "Mixed-Language Programming" chapter of the Intel Fortran Building Applications manual.
0 Kudos
connell
Beginner
2,209 Views

I am still a little confused, what does the complete compiler directive look like? I tried the following and it did not work

subroutine gm_start_cad(igeofile,lugeo_in,isemod,split2)
character*(*) igeofile
logical split2

interface
subroutine gm_start_cad1(igeofile,lugeo_in,isemod,split2)
CDEC$ ATTRIBUTES REFERENCE, DECORATE, STDCALL :: gm_start_cad1
CDEC$ ATTRIBUTES MIXED_STR_LEN_ARG, ALIAS:'GM_START_CAD':: gm_start_cad1
character*80 igeofile
integer lugeo_in, isemod
CDEC$ ATTRUBUTES REFERENCE :: isemod
logical split2
end subroutine gm_start_cad1
end interface

li = len(igeofile)
call gm_start_cad1(igeofile,lugeo_in,isemod,split2)
c
return
c
end
c

0 Kudos
Steven_L_Intel1
Employee
2,209 Views
You misspelled ATTRIBUTES as ATTRUBUTES.
0 Kudos
connell
Beginner
2,209 Views

I have got the call to gm_start_cad working - thanks! I am now using the same technique in a different part of the code to callC routine compiled with cl from Vstudio 6.6 (STDCALL). The C routines I was looking at previously were compiled with VS 2003and /Gz

The interface block is included below. If I compile & linkthis under CVF 6.6c then it runs - as expected, the compiler directivesshould mimick the default calling convention. If I try this under Ifort i get an undefined external

aea_utilities.o : error LNK2019: unresolved external symbol _IOCNTF@136 referenc
ed in function _CHECK4

The library has an entry for _ICONTF@128 (nm -a).

A couple of questions:

a) Has something changed with the @nbytes between 6.6 and ifort?

b) Can I call VS 6.6 C routines from ifort compiled fortran?

interface
subroutine iocntf(ireq,ierror,errmsg,
. cwhat,cwhere,iwhen,
. nattrb, attrbs,
. nstrct, cdtype, block,iaddrs,naddrs,
. cstr, ndums,
. cdum, ndumc,
. idum, ndumi,
. rdum, ndumr,
. ddum, ndumd,
. cldm, nduml)

c#if defined (IWIN32) || DEFINED (IWIN64)
CDEC$ ATTRIBUTES REFERENCE,DECORATE,STDCALL ::iocntf
CDEC$ ATTRIBUTES MIXED_STR_LEN_ARG, ALIAS:'IOCNTF'::iocntf
c#endif
integer ireq, ierror
external errmsg
character*80 cwhat,cwhere
integer iwhen
integer nattrb
character*80 attrbs(20)
integer nstrct
character*80 cdtype
&n bsp; integer block
__io_offset_type__ iaddrs(*)
integer naddrs
character*80 cstr(*)
integer ndums,ndumc,ndumi,ndumr,ndumd,nduml
character*1 cdum(*)
integer idum(*)
real rdum(*)
double precision ddum(*)
character*1 cldm(*)
end subroutine iocntf
end interface
C

0 Kudos
Steven_L_Intel1
Employee
2,209 Views
There should not be any changes in this area - does your C code expect the character lengths to be passed? I'd guess not.

I'm somewhat puzzled by the declarations in your interface block - is cstr really an array of character*80 elements? Is cdum an array of single characters?

If you want the Fortran compiler to not pass the string lengths, you need to add:

CDEC$ ATTRIBUTES REFERENCE :: argname

for each of the CHARACTER arguments. This would have been the case in CVF as well. You don't need the MIXED_STR_LEN_ARG attribute then as there will be no lentgth arguments.
0 Kudos
connell
Beginner
2,209 Views

I think I have figured ot what is going onhere. If I define an interface block as

subroutine gm_tol_cad(tol)
interface
subroutine gm_tol_cad1(tol)
CDEC$ ATTRIBUTES REFERENCE,DECORATE,STDCALL ::gm_tol_cad1
CDEC$ ATTRIBUTES MIXED_STR_LEN_ARG,ALIAS:'GM_TOL_CAD'::gm_tol_cad1
end subroutine gm_tol_cad1
end interface
call gm_tol_cad1(tol)
return
end

The the code links and runs as expected. If I declare tol to be real*8 in the subroutine and interface block them the linker fails looking for _GM_TOL_CAD@8 This seems to imply that the argument length has increased from 4 to 8 bytes whentol is promoted to double precision. With the CVF 6.6 compiler the byte length was always 4 (the address length) irrespective of the precision of tol. Is this the intended behaviour? Is there any way of keeping the 4 byte length

0 Kudos
Steven_L_Intel1
Employee
2,209 Views
There's something missing here. Your interface is for GM_TOL_CAD1 and doesn't declare TOL at all and you don't show the call to GM_TOL_CAD nor how its declaration is visible to the caller (if it is.) The only way that changing a REAL*4 to REAL*8 would change the argument length is if you specified that it was passed by value.
0 Kudos
connell
Beginner
2,209 Views

TheFORTRAN calling routinelooks like.

real*8 tol

call gm_tol_cad(tol)

end

subroutine gm_tol_cad(tol)
real*8 tol
interface
subroutine gm_tol_cad1(tol)
CDEC$ ATTRIBUTES REFERENCE,DECORATE,STDCALL ::gm_tol_cad1
CDEC$ ATTRIBUTES MIXED_STR_LEN_ARG,ALIAS:'GM_TOL_CAD'::gm_tol_cad1
real*8 tol
end subroutine gm_tol_cad1
end interface
call gm_tol_cad1(tol)
return
end

What seems to work is adding an explicit declaration to pass tol by reference .i.e

CDEC$ ATTRIBUTES REFERENCE :: tol

the code now links with tol specified as *4 or *8.

I thought the "REFERENCE" attribute in the first directive would pass everything by REFERENCE. This seems to imply tol gets passed by value unless explicity specified as reference. Am I missing something here?

0 Kudos
Steven_L_Intel1
Employee
2,209 Views
Um., no, that's the way it should work. Something is going very wrong here. Let me investigate.
0 Kudos
Steven_L_Intel1
Employee
2,209 Views
This was indeed a bug that affected the combination of STDCALL and REFERENCE. Unfortunately, the fix almost certainly won't make our August update but it will be in for September.
0 Kudos
connell
Beginner
2,076 Views
Is the workaround of specifying REFERENCE or VALUE for individual arguments ok?
0 Kudos
Reply