FortWrap thread

29 views
Skip to first unread message

Kurt Smith

unread,
Sep 13, 2010, 5:49:16 PM9/13/10
to fwrap...@googlegroups.com
On Mon, Sep 13, 2010 at 1:23 PM, John McFarland <mcfa...@gmail.com> wrote:
>
> Well, I am actually the author and as of now sole maintainer.  I just
> put FortWrap on SourceForge last month, but have been using a
> specialized version of it internally for about a year.
>
> Unlike Fwrap, FortWrap doesn't use a general purpose Fortran parser --
> basically I just wrote the parser myself and have been adapting it as
> new cases have come up.  As far as I know, it should be able to handle
> most F90-F03 constructs and at least print errors/warnings for
> constructs that it doesn't wrap.  I have run it through most of the
> Fwrap test cases, and while not all of those features are supported by
> the wrapper generation (e.g. assumed shape arrays), it at least
> doesn't crash and writes error messages where appropriate.
>
> One construct it doesn't yet handle is a declaration like "integer x"
> (i.e. no "::"), but hopefully I will get that added soon.
>
> Overall, I haven't gotten any feedback on it yet, as it's pretty new,
> so if someone wanted to run some code through it and see how it works
> that would be appreciated.  I'm more than happy to take my best stab
> at fixing any bugs or making any enhancements needed to make it more
> useful (assuming they're not too inconsistent with FortWrap's
> objective, which is wrapping modern code).
>
> John

Hi, John,

I took a look at FortWrap, and have a few questions. Thanks for
drawing our attention to your project.

I see that you use the 'ISO_C_BINDING' interop module, but you don't
use the 'bind(c, name="foo")' feature for the wrapped subroutines, and
reproduce the internal name mangling of g95 and gfortran. Why not
just do

subroutine XYZ() bind(c, name='xyz')
...
end subroutine

and then not worry about reproducing the mangling schemes of the
different compilers? That would give you a significant boost in
portability. Is there something in the compiler implementations that
prevents you from doing this?

Along those lines: as you may know, fortran compilers are allowed to
do whatever the heck they want to the internals of derived types. For
example, if the user had a derived type:

type objectA
integer x
real y
end type

A fortran compiler could switch around the ordering of 'x' and 'y',
add padding, or anything else to the internals of objectA. The
ISO_C_BINDING stuff allows the user to turn all of that off, so a
Fortran derived type matches a C struct definition, and you can pass
back and forth interoperable fortran derived types and C structs
without any copying or accessors. This requires the modification of
the type declaration, however, and may not be an option for legacy
code. The non-interoperability problem is felt especially with arrays
of derived types, which requires a fortran-level call for every access
to a derived type element, which would kill performance. Any thoughts
on how to handle this?

Lastly, I see there is a restriction to arrays of 1 or 2 dimensions
only. Would this restriction be lifted in the future? Is there any
significant reason why it's there currently?

Thanks,

Kurt

John McFarland

unread,
Sep 13, 2010, 6:22:38 PM9/13/10
to fwrap...@googlegroups.com
> --
> You received this message because you are subscribed to the Google Groups "Fwrap Users" group.
> To post to this group, send email to fwrap...@googlegroups.com.
> To unsubscribe from this group, send email to fwrap-users...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/fwrap-users?hl=en.
>
>

Hi Kurt,

Thanks for your interest. There are several reasons for not using
BIND(C). The main reason is that my goal is to wrap derived types and
the approach I use is an "opaque container" approach (a.k.a pointer
handles). The wrappers FortWrap generates allow the derived type data
to be passed around using a pointer/handle, but the internal data
members can not be accessed directly. This follows the object
oriented mindset -- if everything is done using get/set functions,
there is no problem, because the internal data need not be touched
directly from the target language (now I realize this might not be
ideal for wrapping all Fortran code, but wrapping this type of code is
where FortWrap can provide the most benefit).

With the opaque handle approach, FortWrap can create wrappers that
will work regardless of what is stored inside the derived type. For
example, the derived type may contain data with ALLOCATABLE, POINTER,
etc., and it will not be a problem because all the wrapper code does
is obtain a pointer to an instance and pass that around to Fortran
routines that are expecting that pointer.

So this is one reason for not using BIND(C): because this approach
allows me to wrap subroutines that it would not be possible to wrap
using BIND(C) -- e.g. cases where the derived type itself is not
interoperable, so the Fortran code wouldn't compile with BIND(C) (btw
I started what turned out to be a big discussion about this on the
gfortran list a while back:
http://gcc.gnu.org/ml/fortran/2009-06/msg00034.html).

A second reason is to cut down on the amount of code and reduce the
compile time. If FortWrap generated BIND(C) style Fortran wrapper
code for every routine being wrapped, the amount of code and compile
time would go way up.

The third reason is that generation of the wrapper code becomes a
little bit trickier because I would need to be able to reproduce all
of the argument lists and type declarations in the Fortran BIND(C)
wrapper routines (I assume sort of like Fwrap does when wrapping
routines that contain assumed size arrays). I'm not too far from
being able to do this though, so the main reasons are the first two.

Based on my opaque container approach it should be clear why I'm not
concerned about the compiler's internal representation of the derived
type. Re your question about performance of derived type
interoperability, I'm not completely sure I understand what the issue
is, but in general my recommendation would be to augment the original
Fortran code with accessor functions and use those instead of directly
accessing the data from C. Then only pointers are passed around so it
shouldn't incur a performance hit. I haven't yet figured out a good
way to work with arrays of derived types (aside from creating a new
derived type that contains them).

Regarding array dimensionality: I rarely use arrays with 3 or more
dimensions in my work so hadn't had the need. I guess the main issue
would be making sure the data order is compatible. Currently FortWrap
creates a C++ class for handling two-dimensional arrays, and this
class takes care of storing data in Fortran order but letting C++ code
access the data as if it were in C order. This approach could
probably be extended, although it isn't super elegant as it introduces
an intermediary class.

Thanks for your comments. It will be good to have someone to bounce
ideas off of.
John

John McFarland

unread,
Sep 14, 2010, 4:38:34 PM9/14/10
to fwrap...@googlegroups.com
Just wanted to add a small clarification here. I said that it wasn't
possible to wrap non-interoperable (a.k.a "deep" or "complicated"
derived types) derived type procedure arguments using BIND(C). That
isn't completely true. What you can do is create a BIND(C) wrapper
that accepts a TYPE(C_PTR), and then use C_F_POINTER in the wrapper to
extract a Fortran pointer to the derived type and pass that to the
original Fortran procedure.

This might be of interest as an approach for wrapping deep derived
types in a portable, standard-compliant way. Basically I haven't used
this approach in FortWrap for the reasons I mentioned above
(additional wrapper code, more complicated, etc.) g95 and gfortran,
at least, implement derived type procedure arguments by simply passing
a pointer to the data, so I haven't found it necessary to go the extra
mile and make that wrapping standard compliant with BIND(C).

John

Reply all
Reply to author
Forward
0 new messages