Bind(c) for procedures with complicated derived types

John McFarland john.mcfarland@swri.org
Wed Jun 3 16:32:00 GMT 2009


Hi Dennis, thanks for your reply.

Dennis Wassel wrote:
> Hi John,
> 
> 2009/6/3 John McFarland <john.mcfarland@swri.org>:
>> We have a large project that makes extensive use of complicated derived
>> types (i.e. they contain pointer arrays, allocatable arrays, other derived
>> types, etc).  We can currently use the functions and subroutines that
>> operate on these derived types from C code, without any use of BIND(C), by
>> making use of opaque containers; that is, the C prototype just has void*
>> where the derived type argument is, and we pass around some chunk of memory
>> (maybe an array of floats) that is big enough to contain the Fortran type.
>>  This acts like a handle to the derived type and allows us to call all of
>> its functions from C code.
> 
> I tried going down that road once, but my experience is that this will
> bite you some day. Good for you if it hasn't so far!
> (I could never get this construction to run from a C main, for
> instance, because the pointer and allocatable components want to be
> "initialised" instead of just having memory to write into)

The Fortran compiler may provide some "initialization" functions that 
you can call from C.  g95 provides a function like this, although 
curiously, we've never needed it.

> 
>> However, we now want to go through and add BIND(C) to all of our
>> subroutines, so that we can get particular symbol names in the symbol table,
>> as opposed to __modname_MOD_funcname (which aside from being ugly in C, is
>> compiler-dependent).  The problem is gfortran gives an error stating that
>> the derived type argument must be interoperable, but I can't add BIND(C) to
>> the derived type declarations because they contain non-primitive data.
>>  Below is an example that shows the type of code I am trying to compile
>> (this example will compile with g95):
>>
>> MODULE mod
>>  TYPE Structure
>>    INTEGER, POINTER :: x(:)
>>  END TYPE Structure
>> CONTAINS
>>  SUBROUTINE sub(s) BIND(C)
>>    TYPE (Structure) :: s
>>    ! Do something with s
>>  END SUBROUTINE sub
>> END MODULE mod
> 
> I'd consider this as a bug rather than a feature of g95.
> The background is that in memory, the pointer component will be a
> compiler-dependent array descriptor that holds type, stride and extent
> information, rather than just a C pointer. If you know this structure,
> you can access it from C, but (for the time being) the companion C
> compilers don't have a clue about Fortran array descriptors. Fortran
> 2008 will define headers and macros to overcome that limitation.
> If you want to take this path, there is the chasm interop API, which
> hides this complexity from you for a limited number of compilers. Be
> warned, though, that this is version-, compiler- and maybe even
> platform-specific.

I understand that the pointer components do not just contain "raw 
pointer" information that could be accessed from C, but this is why the 
opaque container approach works: I am not asking the C program itself to 
try and interpret any of the memory stored in the Fortran derived type. 
  All I am asking it to do is hold that memory so I can pass it around 
to various Fortran functions that do useful things with it.

> 
>> Is there any way in gfortran to inhibit the compiler error and allow the
>> program to compile?  If not, this seems like a limitation because the
>> "opaque container" approach is a very powerful way of interfacing with C
>> without defining "interoperable" derived types.
> 
> If you ask me, the opaque container approach is yet another glorious
> way to Shoot Yourself In The Foot (TM) with C, but you certainly have
> a right to your own opinion! :-)

Thanks for your input, Dennis, but I have to disagree with this.  The 
opaque container approach has been published in Computing Science and 
Engineering: http://portal.acm.org/citation.cfm?id=1383121.  We have 
used it successfully with our large Fortran project to make interfaces 
to C, Matlab, Python, and Excel (no kidding), although admittedly we 
have not yet tested these interfaces with our library compiled by 
gfortran (we have previously been using g95 although now we are just 
starting to use gfortran as well thanks to Janus Weil's recent work on 
procedure pointer components).

> 
> I know of know way to inhibit these (justified!) error messages, see above.

 From the perspective of true "interoperability", I understand the 
justification for the error messages.  In fact I really don't need to 
use BIND(C), I just want to change the names in the symbol table so they 
are not compiler-specific.

> 
> The other possible path to take is to make your Fortran structures
> C-interoperable. I went down this (admittedly ugly) path, because I
> could not wait until compiler support for Fortran 2008 was widely
> available. Technically, you "just" replace all non-interoperable
> things with C_PTR and use the C_F_POINTER intrinsic for the Fortran
> parts. This is ugly, but it works.

Our use of Fortran derived types is very extensive, and in fact some 
serve the sole purpose of creating a "dynamic dispatching" effect of 
calling a particular procedure depending on which pointer components are 
associated.  It is simply not practical for us to make our derived types 
interoperable; nevertheless, if we went that path, it would be hard to 
justify the use of Fortran at all.

> 
> Cheers,
> Dennis

Like I mentioned above, we don't necessarily need to use BIND(C), we 
just want to change the way the function names are written to the symbol 
table.  I don't guess there is a compiler flag that could control this 
behavior?

Thanks,
John



More information about the Fortran mailing list