Linked-list example with c-interoperablility

Linked-list example with c-interoperablility

Post by Simon » Sat, 23 Jun 2007 22:10:18

Now that I've got my linked-list code working I want to move on to c-
interoperability. My intention is to create a c-version of the length
procedure My first question is what is the correct syntax for
declaring a structure containing a pointer. My first effort is

module Poly
use iso_c_binding

type, bind(c) :: point
real(c_double) :: x ! x-component of coordinate
real(c_double) :: y ! y-component of coordinate
end type point

type, bind(c) :: polyLine
type(Point) :: p
type(polyLine), pointer :: next => null()
end type polyLine

! /* C equivalent */
! typedef struct {
! double x,y;
! } point

! typedef struct {
! point p;
! polyLine* next;
! } polyLine


! ... code unchanged from last post in 'Linked-list example

The compiler gives an error:

$ g95 -o rope Poly.f90 rope.f90
In file Poly.f90:11

type(polyLine), pointer :: next => null()
Error: POINTER component 'next' of type 'polyline' at (1) conflicts
with BIND(C) attribute

Any ideas much appreciated.

Simon Geard

Linked-list example with c-interoperablility

Post by nospa » Sat, 23 Jun 2007 23:54:44


It's not that simple. Fortran pointers do not interoperate directly with
C pointers. For arrays, they pretty much can't, as a Fortran array
pointer has to have a lot more information than a C pointer. For scalar
pointers, the most common implementations look alike underneath, but the
standard doesn't assume or require that.

A C pointer of any type interoperates with a Fortran variable of the
special type C_PTR (which is in the ISO_BIND_C intrinsic module). So you
have to do something more like (untested)

type, bind(c) :: polyline
type(point) :: p
type(c_ptr) :: next => c_null_ptr
end type polyline

I've also used the c_null_ptr named constant in the initialization. Note
that although I showed how to do the initialization, and it is allowed,
that is not actually equivalent to the C struct shown. To my knowledge,
C doesn't have anything like that. You can interoperate like that, but
don't expect the Fortran initialization to somehow magically apply to C
code. It doesn't. If you create variables of the struct type in C, they
won't be automatically initialized.

That should get you past that first step, but you'll quickly see another
complication. The "next" component here is a variable of type c_ptr -
not a Fortran pointer. If you want C interop, that's what you need to
do. But now it isn't a Fortran pointer, so you can't do Fortran pointer
stuff with it - at least not directly. See the procedures C_LOC and
C_F_POINTER in the ISO_C_BINDING intrinsic module. They are what you
need to translate between Fortran and C pointers.

Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain