Showing results for 
Search instead for 
Did you mean: 

Derived Types and C interoperability

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

            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



      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 



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

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

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?


-- Nick






0 Kudos
1 Reply

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