From: Richard Maine on
steve <kargls(a)comcast.net> wrote:

> That does not answer my question. AFAIU, the
> routine cannot be USEd in any other fortran
> procedure.

False. This sounds like a fairly basic misunderstanding of bind(c).
Bind(c) does not mean that something cannot be invoked from Fortran. It
just means that the invocation method is compatible with C.

There are actually 2 completely different ways that a bind(c) module
procedure can be invoked from Fortran code.

The first way is via C interop. A bind(c) procedure is compatible with
invocation via C. We know how to invoke C compatible procedures. Put the
two together, and viola. This is independent of whether the procedure is
in a module or not. It is a little wordy in this case because of the way
that the type info_t is defined within the function. (I wouldn't do it
that way, but it is allowed). That means I end up having to repeat the
darned thing 3 times: 1) within the function itself, 2) within the
interface body that is needed where we invoke the function, and 3 within
the scope where we invoke the function because we'll need it to declare
the actual argument. Wordy, but valid. The following wordy code works
fine in g95 and prints 0 as expected. I have not touched a character of
the original module.

MODULE liter_cb_mod
USE ISO_C_BINDING
CONTAINS
FUNCTION liter_cb(link_info) bind(C)
USE ISO_C_BINDING
IMPLICIT NONE

INTEGER(c_int) liter_cb

TYPE, bind(C) :: info_t
INTEGER(c_int) :: type
END TYPE info_t

TYPE(info_t) :: link_info

liter_cb = 0

END FUNCTION liter_cb

END MODULE liter_cb_mod

PROGRAM main
USE ISO_C_BINDING
interface
FUNCTION liter_cb(link_info) bind(C)
USE ISO_C_BINDING
IMPLICIT NONE
INTEGER(c_int) liter_cb
TYPE, bind(C) :: info_t
INTEGER(c_int) :: type
END TYPE info_t
TYPE(info_t) :: link_info
END FUNCTION liter_cb
end interface

TYPE, bind(C) :: info_t
INTEGER(c_int) :: type
END TYPE info_t
type(info_t) :: link_info

write (*,*) liter_cb(link_info)

END PROGRAM main

Nag has a problem, but I'll cover that below.

The second way to invoke a bind(c) procedure defined in a module is to
USE the module. The rules for USE do not have any exceptions for bind(c)
procedures. That means they are supposed to work. Yes, that means that,
among other things, USEing the module has to pass along the information
that the procedure in question is a bind(c) ones. But then USEing a
module is supposed to simillarly pass along darn near everything. The
following much shorter main program uses this method. I elided the
module here because it is also unchanged from the original and one copy
per post seemed enough

PROGRAM main
use liter_cb_mod
TYPE, bind(C) :: info_t
INTEGER(c_int) :: type
END TYPE info_t
type(info_t) :: link_info

write (*,*) liter_cb(link_info)

END PROGRAM main

This also works fine and gives the expected result with g95. Again, Nag
fails on it.

The problem with the Nag compiler here isn't directly related to
invoking a bind(c) module procedure. It has more to do with the bind(c)
type used for the argument. In the version with the USE statement, Nag
(v 5.2 on my Mac) gives me the message

Incorrect data type INFO_T (expected INFO_T) for argument
LINK_INFO (no. 1) of LITER_CB

The message about finding INFO_T when it expected INFO_T looks confusing
on the surface, but I think I can interpret it, realizing that there are
2 separate declarations of types named INFO_T. I'm thinking that someone
at Nag forgot that bind(c) acts like sequence in that you can have 2
separate declarations that count as the same type.

I'll throw in yet another lament that J3 failed to understand my
suggestion that bind(c) types be referred to as a special sort (I
carefully avoid saying type, kind, class or a bunch of other words that
are basically synonymous in English, but have special meaning in
Fortran) ot sequence type. They really do act like sequence. Pretty much
everywhere the standard previously said "sequence", it had to be
modified to say "sequence or bind(c)". There were several errors made in
missing some such places in drafts of f2003. If we had just said that
bind(c) was a sort of sequence, the errors would not have happened.
Looks like compilers might be prone to exactly the same error. Think
I'll submit a bug report on this one to Nag (after checking to make sure
I have the most current patch release installed; I haven't checked that
yet).

Anyway, if I move the derived type definition out to module scope, where
I would normally put it if I were writing the code, then the whole thing
becomes

MODULE liter_cb_mod
USE ISO_C_BINDING
TYPE, bind(C) :: info_t
INTEGER(c_int) :: type
END TYPE info_t

CONTAINS
FUNCTION liter_cb(link_info) bind(C)
USE ISO_C_BINDING
IMPLICIT NONE

INTEGER(c_int) liter_cb


TYPE(info_t) :: link_info

liter_cb = 0

END FUNCTION liter_cb

END MODULE liter_cb_mod

PROGRAM main
use liter_cb_mod

type(info_t) :: link_info

write (*,*) liter_cb(link_info)

END PROGRAM main

which works fine with both Nag and g95 on this machine.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: dpb on
Richard Maine wrote:
....

> There are actually 2 completely different ways that a bind(c) module
> procedure can be invoked from Fortran code.
>
> The first way is via C interop. A bind(c) procedure is compatible with
> invocation via C. We know how to invoke C compatible procedures. Put the
> two together, and viola. ... we have string music in an alto range. :)

<Yeah, I know, groan, but I simply couldn't help it, Richard! :) >

--
From: Richard Maine on
dpb <none(a)non.net> wrote:

> Richard Maine wrote:
> ...
>
> > There are actually 2 completely different ways that a bind(c) module
> > procedure can be invoked from Fortran code.
> >
> > The first way is via C interop. A bind(c) procedure is compatible with
> > invocation via C. We know how to invoke C compatible procedures. Put the
> > two together, and viola. ... we have string music in an alto range. :)
>
> <Yeah, I know, groan, but I simply couldn't help it, Richard! :) >

Voila! :-)

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: glen herrmannsfeldt on
Richard Maine <nospam(a)see.signature> wrote:
(snip)

> There are actually 2 completely different ways that a bind(c) module
> procedure can be invoked from Fortran code.

I presume that is in addition to calling a C function that
calls the bind(c) module procedure from a passed c_funloc()
pointer.

-- glen
From: Richard Maine on
glen herrmannsfeldt <gah(a)ugcs.caltech.edu> wrote:

> Richard Maine <nospam(a)see.signature> wrote:
> (snip)
>
> > There are actually 2 completely different ways that a bind(c) module
> > procedure can be invoked from Fortran code.
>
> I presume that is in addition to calling a C function that
> calls the bind(c) module procedure from a passed c_funloc()
> pointer.

Well yes, that's a third. I suppose I could have overlooked others as
well.

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