Exploring ISO_C_BINDING and type-bound procedures

Exploring ISO_C_BINDING and type-bound procedures

by Rohit Goswami
Written: 2021-12-19 16:25 +0000
Table of Contents

A closer look at the standard Fortran C compatibility layer by exploring objects and linkers

2 Likes

Sorry but kinda feels like you might have missed all the text associated with the code blocks. The BIND(C) attribute does not work with type bound procedures, and this demonstrates that mucking around with the function name will work for generating wrappers to types with such procedures…

Additionally, VALUE doesn’t seem to have anything to do with the current post at all, it enforces call-by-value when specified [1], and is only relevant in that when a subprogram has BIND(C) it may not additionally be OPTIONAL [2]…

It would be great to hear your standards conforming bind(c) method for type-bound procedures though :slight_smile:

[1] IBM Docs
[2] https://j3-fortran.org/doc/year/21/21-007.pdf

Thanks for catching the typos. Updating it to the actual test code. Anyway, don’t let the poor quality of the article stop you from responding to the rest of my queries :slight_smile:

Sorry, but your entire approach is doomed to failure. First, a bugaboo of mine - the C interoperability features are not defined by intrinsic module ISO_C_BINDING, and I wish people would stop referring to the module when they mean the interop features. The module is helpful but not a requirement to use the C interop features.

Never, ever use “renaming” to work around such things as module procedure global names. You can declare that module-contained procedures have the BIND(C) attribute, at which point you can specify their external name, or use the default which is downcased and then any decoration the “companion C processor” would use is applied.

As for type-bound procedures and polymorphic (CLASS) entities - these are simply not interoperable, so don’t fool yourself into thinking you can make them so. Maybe you can tie yourself in knots with a particular compiler and get some simple examples to work, but it would be a huge disservice to use this as an example for others.

2 Likes

Renaming is definitely not recommended in the post, I should be more explicit. I was using the objcopy stuff to try to describe the effect of the interoperability functionality. In no way do I think there can be any sort of toolchain or program involving liberal usage of objcopy for anything in production.

As for the type bound procedures and CLASS entities, since the goal is really calling them from Python, it should be (is?) legal to have a wrapper function which takes in a type instance and executes the call. Actually, since such a function would require the size of the type, it is easier to pass a pointer to said type instance; the size of which is specified by the compiler and fixed. This is, from my understanding is the “Pointer to an Opaque Container” method described in the literature [1] and seems reasonable, if a bit clunky. I’ll be looking into it for a few compilers soon, but it certainly seems alright so far.

As far as them simply not being interoperable, in this approach they are called from the Fortran side only, with the C / Python coprocessor only receiving the results, so they don’t need to be interoperable in the same way say, c_double and double are. From a “binding generating” perspective (e.g. F2PY), as long as automated code can be written to mimic the effects of the underlying Fortran code that’s good enough.

[1] Pletzer, Alexander, Douglas McCune, Stefan Muszala, Srinath Vadlamani, and Scott Kruger. 2008. “Exposing Fortran Derived Types to C and Other Languages.” Computing in Science Engineering 10 (4): 86–92. Exposing Fortran Derived Types to C and Other Languages | IEEE Journals & Magazine | IEEE Xplore.

2 Likes

Thanks much for writing an interesting article. I didn’t know the command objcopy up to now… :slight_smile:

From the bottom part of the article, it seems (to me) that the ultimate goal is to pass a pointer (to some struct object in C etc) to Fortran and call type-bound procedures somehow? If direct “mapping” of the actual struct data/fields to that in Fortran is not necessary, I guess another option might be to send the pointer as c_ptr and use c_f_pointer() on the Fortran side, as used in a recent Cython example (by Nicholaswogan, thanks!).

Also, for the name mangling of a procedure that receives a type argument, another option might be to declare a wrapper Fortran routine outside a module (i.e., with no explicit interface) and then call such an external routine directly from C? Something like…

module foo_mod
...  !! type and procedure definitions
end module

subroutine set_a( self, a )   !! C name typically "set_a_()" etc
   use foo_mod
   type(foo_t) :: self
   integer :: a
   self% a = a
end

PS. I’ve just noticed that a similar thing may be written in the IEEE article right above… XD
(if so, I’m sorry for a very redundant post)

3 Likes