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.
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.
Thanks for your help. I really appreciate your time!