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

Derived Types and C interoperability

Nick_M_2
Beginner
520 Views

In the previous version of the compiler, we have setup a nice system:

 

      MODULE SMAVector

      use ISO_C_BINDING

      !-----------------------------------------------------------------
      TYPE, BIND(C) ::  SMAVectorDouble

           integer(kind=4) :: len = 0
           integer(kind=4) :: fin = 0
           integer(kind=8) :: ptr = 0 ! pointer to the actual data

      CONTAINS
       
            procedure, pass :: At      => SMAVectorDoubleAccess 
            procedure, pass :: Append  => SMAVectorDoubleAppend1
            procedure, pass :: Load    => SMAVectorDoubleLoad
            procedure, pass :: Free    => SMAVectorDoubleFree
            procedure, pass :: Reserve => SMAVectorDoubleReserve

      END TYPE SMAVectorDouble

      !-----------------------------------------------------------------
      INTERFACE SMAVectorDoubleAppend

      subroutine SMAVectorDoubleAppend1(self,val) bind(C)
           import :: SMAVectorDouble
           type(SMAVectorDouble)   :: self
           real (kind=8)           :: val
      end subroutine 

      END INTERFACE SMAVectorDoubleAppend

      INTERFACE

      INTERFACE

      function SMAVectorDoubleAccess(self, pos) bind(C)
           import :: SMAVectorDouble
           real (kind=8)          :: SMAVectorDoubleAccess ! return the value of v(pos)
           type(SMAVectorDouble)  :: self
           integer (kind=4)       :: pos     ! position in the array
      end function

      subroutine SMAVectorDoubleReserve(self, n) bind(C)
           import :: SMAVectorDouble
           type(SMAVectorDouble)  :: self
           integer (kind=4)       :: n     ! number of doubles
      end subroutine 

      subroutine SMAVectorDoubleFree(self) bind(C)
           import :: SMAVectorDouble
           type(SMAVectorDouble)  :: self
      end subroutine 

      END INTERFACE


      END MODULE 

As you can see, this type is essentially a Fortran binding to std::vector. It contains the same data members: ptr ( raw pointer to allocated data ), len and fin. It contains bound methods, allowing for a simple use:

      use SMAVector
       
      type(SMAVectorDouble)::  v  ! Declare v as Vector of doubles

      call v % Append(100.d0)
      call v % Append(200.d0)
      call v % Append(300.d0)
      
      do k = 1, v%len
         sum = sum + v % At(k)
      end do

      call v % Free()

The actual methods were implemented in C++. Everything worked, no problems.

This was with Intel(R) Fortran Intel(R) 64 Compiler XE Version 12.1.4.319.

Then came Intel(R) Fortran Intel(R) 64 Compiler, Version 16.0.1.150

Now everything fell apart.

It insists that derived types which have bound procedures cannot be declared with BIND(C) attribute.

If you remove BIND(C), C++ implementation cannot read the arguments anymore.

I found a workaround for this, which is nesting a 'BIND(C)' type inside the derived type, but it looks clumsy and non-elegant.

So,  some questions for the experts:

1. Why was this done? Why was this neat interoperability abandoned?

2. Can it be restored?

      Are there any !DEC directives that would change the behaviour to the old one ?

      Are there really any performance benefits for not-storing the data members ( variables of a type ) in a way the C understands them?

      Could we rally for the change of standard to allow derived types to be accessible from C/C++, even if they have methods bound to them?

You guys have obviously figured all of this out, in your compiler version 12, quite some time ago. Why did you have to break it for the newer versions?

Thanks,

-- Nick

 

 

 

 

 

0 Kudos
1 Reply
Steven_L_Intel1
Employee
520 Views

It was a compiler bug that allowed you to say that a type with type-bound procedures was interoperable. The standard explicitly says they are not.

C1504 (R425) A derived type with the BIND attribute shall not have a type-bound-procedure-part .

Fortran's interoperability is with C, not C++. While you may think that there is a correspondence between the Fortran type with type-bound procedures and a C++ structure with methods, the data passed for these is very different and not interoperable.

0 Kudos
Reply