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