Help with Fortran Wrapper that Interfaces with C Library

Help with Fortran Wrapper that Interfaces with C Library

Dear Fortran Gurus,

Let me begin with a disclaimer. I'm not a Fortran developer, but a library that I've written has been adopted by some parallel scientific codes written in Fortran, so I thought I would provide a nice interface to said codes. Until yesterday, I thought I was successful in doing so. I need help. Maybe I'm doing something funky in my C wrapper written in Fortran. I'll get into this later, but my wrapper works perfectly with Intel 13.1.3 20130607, but is completely broken with Intel 14.0.1 20131008. For what it is worth, my Fortran interface also works with all the GFortrans that I've tried.

Background

I have a C library that operates on opaque handles (pointers to opaque typedef'd structs). Users never directly operate on the data contained within these handles (I call them contexts). The first call into my library would look something like (C):

// in my library's header, this is what QUO_context looks like
struct QUO_t;                                                                           
typedef struct QUO_t QUO_t;                                                           
/* external QUO context type */                                                        
typedef QUO_t * QUO_context;
// the definition of QUO_t is in a .c file "hidden" from the rest of the world

// this is an example of how a user would interact with my library in C
QUO_context q = NULL;
QUO_create(&q); // allocates and initializes the context.
// NOTE: QUO_create's signature is really QUO_create(QUO_t **t);
// So, q will point to the allocated struct when the call returns. 
QUO_free(q); // tears down and frees all the initialized infrastructure

A n00bs Fortran Interface

I would like to retain the same abstraction that I've provided in the C interface. That is, I don't want the users to allocate/free the context explicitly. I want the library to do all that in C land and simply set the provided quo_context such that it points to the initialized QUO_t. I thought I had succeeded in doing so, but it appears as if there is a difference between Intel 13.1.3 20130607 and 14.0.1 20131008.

This is what my Fortran interface looks like (any suggestions in implementing this in idiomatic Fortran is also welcome!)

module quo
      use, intrinsic :: iso_c_binding
      type, bind(c) :: quo_context
          type(c_ptr) :: qcp
      end type quo_context
interface
      integer(c_int) &
      function quo_create_c(q) &
          bind(c, name='QUO_create')
          use, intrinsic :: iso_c_binding, only: c_int
          import :: quo_context
          implicit none
          type(quo_context), intent(out) :: q
      end function quo_create_c
end interface

interface
      integer(c_int) &
      function quo_free_c(q) &
          bind(c, name='QUO_free')
          use, intrinsic :: iso_c_binding, only: c_int
          import :: quo_context
          implicit none
          type(quo_context), value :: q
      end function quo_free_c
end interface
contains
      subroutine quo_create(q, ierr)
          use, intrinsic :: iso_c_binding, only: c_int
          implicit none
          type(quo_context), intent(out) :: q
          integer(c_int), intent(out) :: ierr
          ierr = quo_create_c(q)
      end subroutine quo_create

      subroutine quo_free(q, ierr)
          use, intrinsic :: iso_c_binding, only: c_int
          implicit none
          type(quo_context), value :: q
          integer(c_int), intent(out) :: ierr
          ierr = quo_free_c(q)
      end subroutine quo_free
end module quo

And the user would interact with the Fortran interface thusly:

program quofort
    use quo
    use, intrinsic :: iso_c_binding
    implicit none
    type(quo_context) quoc
    call quo_create(quoc, info)
    call quo_free(quoc, info)
end program quofort

With Intel 13.1.3 20130607, quoc correctly "points" to the allocated struct and I can pass this around within the Fortran code with no problems. With Intel 14.0.1 20131008, quoc doesn't get set properly. What am I doing wrong?

Hopefully this post makes sense.

If this makes things easier, below is a link to the full source.

https://github.com/losalamos/libquo/blob/master/src/quof.f90

Thanks for your help. I really appreciate your time!

-- Sam

Sam
Los Alamos National Laboratory
3 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Best Reply

Update to 14.0.2. The version you're using has a bug when passing small structures by value.

Steve - Intel Developer Support

Thanks! I appreciate the quick response. Will do.

Quote:

Steve Lionel (Intel) wrote:

Update to 14.0.2. The version you're using has a bug when passing small structures by value.

Sam
Los Alamos National Laboratory

Leave a Comment

Please sign in to add a comment. Not a member? Join today