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

Fortran Calling C Example Docs

New Contributor III

In I copied code and changed only to cpp with extern"C". Iam getting error that I don't understand: error #6646: ALLOCATABLE or POINTER attribute dictates a deferred-shape-array.   [RECVCOUNTS].


module ftn_C_2
     integer (C_INT) function CPP_Library_Function & 
     (sendbuf, sendcount, recvcounts) & 
        BIND(C, name='CPP_Library_Function') 
        use, intrinsic :: ISO_C_BINDING  
        implicit none 
        type (C_PTR), value :: sendbuf 
        integer (C_INT), value :: sendcount 
        type (C_PTR), value :: recvcounts 
     end function CPP_Library_Function 
   end interface 
end module ftn_C_2
!  ftn_c.f90 
!  ftn_c - Entry point of console application.

!  PROGRAM: ftn_c
!  PURPOSE:  Entry point for the console application.
program ftn_c
use, intrinsic :: ISO_C_BINDING, only: C_INT, C_FLOAT, C_LOC 
use ftn_C_2 
implicit none

! Variables
real (C_FLOAT), target :: send(100) 
integer (C_INT) :: sendcount 
integer (C_INT), ALLOCATABLE, target :: recvcounts(100)

! Body of ftn_c
    ALLOCATE( recvcounts(100) ) 
    CRET = CPP_Library_Function(C_LOC(send), sendcount, C_LOC(recvcounts)) 
    print *, 'Hello World'
end program ftn_c


extern "C" int CPP_Library_Function(void* sendbuf, int sendcount, int *recvcounts) {
	return 0x11;


0 Kudos
4 Replies
Honored Contributor II

Given the ALLOCATABLE attribute of 'recvcounts' array, the compiler is asking you to declare it using the deferred shape notation i.e., using colon syntax ":" rather than as fixed-size:

integer (C_INT), ALLOCATABLE, target :: recvcounts(:)


Black Belt Retired Employee

The example is wrong. The declaration of revcounts should be (:), not (100).

It's also a terrible example and its style should not be followed. I'll forgive, somewhat, the use of a C_PTR passed by value for the sendbuf argument, as until version 16 that was probably the best way to do that. I won't forgive use of C_PTR by value for recvcounts, this is just an INTEGER(C_INT) without VALUE.

Nowadays sendbuf should be declared in the interface as TYPE(*). In the caller, recvcounts doesn't need the TARGET attribute and should just be passed normally, not with C_LOC.

It's interesting that I have never seen this example before. I'll write up a request for an update/correction and send it to Intel.

New Contributor III

Thanks to both "best" answers. Is there documentation anywhere for current best interop practices?

Black Belt Retired Employee

I don't know of documentation, but my view is "simpler is better". There's rarely need to fuss with C_PTRs, though sometimes it's required. Use the features the language provides, including TYPE(*) for void. Use VALUE only when the C prototype uses by-value. Be careful about character arguments, especially now that CHARACTER(*) is allowed in an interoperable interface, but it requires use of a "C descriptpor" on the C side.

I gave a presentation at the University of Tokyo recently on Fortran 2018, including the interop stuff. I'll post that in a separate topic. (Intel Fortran 16 and later supports all of the F18 interop features.)