procedure() pointer

  • Follow


Hi, i am trying to do the following, with no success whatsoever:

create a type (myType), that has a procedure() pointer. Then this
pointer must point to a subroutine that receveis a myType argument.
Something like this:

in an module: module1
"
use myType_module
....
contains
subroutine test(A)
   ...
   type(myType) , intent(inout) :: A
   ...
end subroutine test
"

in myType_module:
"
type myType
   ...
   procedure() , pointer , nopass :: ptr
end type myType
"

How do I make ptr point to the subroutine test ?
ptr => test
dont work, so I am guessing its something about the lack o a interface
for test. But how can I make such an interface if test needs myType to
be declared?

Any help?
Thanks in advance =)
0
Reply Felipe 10/29/2010 1:26:07 PM

Felipe Nunes Franco <felipenfranco@gmail.com> wrote:

> Hi, i am trying to do the following, with no success whatsoever:
> 
> create a type (myType), that has a procedure() pointer. Then this
> pointer must point to a subroutine that receveis a myType argument.
> Something like this:
> 
> in an module: module1
> "
> use myType_module
> ...
> contains
> subroutine test(A)
>    ...
>    type(myType) , intent(inout) :: A
>    ...
> end subroutine test
> "
> 
> in myType_module:
> "
> type myType
>    ...
>    procedure() , pointer , nopass :: ptr
> end type myType
> "
> 
> How do I make ptr point to the subroutine test ?
> ptr => test
> dont work, so I am guessing its something about the lack o a interface
> for test. But how can I make such an interface if test needs myType to
> be declared?

Hmm. Minorly tricky - enough so that I better test before posting an
answer... ok.

You will need some f2003 features mentioned below. You are already using
some, but you will need others as well. Insert here my usual gripe about
not liking to paw through detailed lists of what features are supported,
but preferring to just be able to specify something like "f2003
standard".

You don't say why the pointer assignment doesn't work. (General hint for
asking sich questions: "Doesn't work" is almost always inadequate
description. That could mean any number of things, including that it
compilers and gives incorrect results, gives an error message, etc. For
a compilation error, you should quote the exact error message. I think I
can guess this one, but for future purposes one should say what it
*DOES* do - i.e. generate a particular error message - instead of what
it doesn't do.)

If I guess correctly, your problem in the pointer assignment is
incompatible interfaces. (I haven't played with f2003 procedure pointers
a lot, as I have access to no full-language f2003 compilers, so I'm a
little vague on some esoteric things such as the form of procedure
declaration statement that you are using here. Its a valid form, but I'm
a little hazy on when you can get by with it, as it doesn't even specify
whether the procedure is a subroutine or function). Anyway, I'll assume
that the interface needs to be specified.

The main problem here is one of recursive definition - that the
definition of myType needs to refer to the definition of a procedure,
which in turn refers to the definition of myType. You can do that in
some cases (including this one), but it can be tricky to get right.

I'll start out by putting everything into one module because that avoids
one of the complications. I'll do the 2-module case later. In one module

module myType_module
  type myType
    procedure(test), pointer, nopass :: ptr
  end type myType
  contains
    subroutine test(a)
      type(myType), intent(inout) :: a
    end subroutine test
end module
program main
  use myType_module
  type(myType) :: variable
  variable%ptr => test
end program main

Note that the procedure declaration statement refers to the test
procedure. That form of procedure declaration statement specifies that
the interface of the procedures being declared is the same as that of
the referenced one (test in this case). This is the form of procedure
declaration statement that I generally prefer because it allows
specifying an explicit interface without needing to write out a separate
interface body. It does assume that there is a handy accessible
procedure with the right interface, but there often is.

I compiled and ran the above code with the nag compiler. Not that it has
any output to show, but it at least compiled with no error messages
(other than some warings about using an f2003 feature and about an
unused dummy argument) and ran without crashing.

But you wanted test to be in a separate module. That adds extra issues
because the two modules can't reference each other, even indirectly. The
module that defines the subroutine will need to use the one that defines
the type - no way around that. But the module that defines the type can
avoid using the one that defines the subroutine; we write out an
interface body instead. This interface body is going to need to use
another f2003 feature: the IMPORT statement. (This post is long enough,
so I'll skip my usual tirade about the sorid history of the import
statement). Thus

module myType_module
  type myType
    procedure(myproc), pointer, nopass :: ptr
  end type myType
  interface
    subroutine myproc(a)
      import myType
      type(myType), intent(inout) :: a
    end subroutine myproc
  end interface
end module myType_module
module module1
  use myType_module
  contains
    subroutine test(a)
      type(myType), intent(inout) :: a
    end subroutine test
end module module1
program main
  use module1
  type(myType) :: variable
  variable%ptr => test
end program main

This one also compiles and runs with the NAG compiler. It adds another
warning message, as import is also an f2003 feature.

Some people have been known to be confused about an ordering requirement
related to this example. The procedure declaration statement for ptr
above refers to the interface myproc, which isn't defined until later in
the code. That is allowed. There is a prohibition against a simillar
case, but it only applies when myproc is also defined by a procedure
declaration statement - not when myproc is defined by an interface body
like this (or by a procedure like in the one-module example above).

Speaking of ordering, I think you ought to be able to swap the order of
the interface block and the type declaration in this code, but NAG
doesn't like it when I do that. It says

  Cannot IMPORT MYTYPE from host MYTYPE_MODULE - it does not exist

presumably because the definition of mytype is later in the code. I
think this is a bug, but it does require slightly careful reading to
conclude that and I'm not 100% sure. Maybe I'll send it to NAG and see
what Malcolm says.

I don't see any restriction that says the imported names have to be
defined prior to the interface body. They certainly have to be in the
host scoping unit - that is a straightforward constraint - but I don't
see any ordering requirement. Maybe I missed it. There is an ordering
requirement relating to defining a type before using it in a type
declaration statement, but getting the type by host association avoids
that requirement as far as I can see, even if the definition in the host
isn't until later.

-- 
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
0
Reply nospam 10/29/2010 5:03:20 PM


On 10/29/2010 07:03 PM, Richard Maine wrote:
> module myType_module
>   type myType
>     procedure(myproc), pointer, nopass :: ptr
>   end type myType
>   interface
>     subroutine myproc(a)
>       import myType
>       type(myType), intent(inout) :: a
>     end subroutine myproc
>   end interface
> end module myType_module
> module module1
>   use myType_module
>   contains
>     subroutine test(a)
>       type(myType), intent(inout) :: a
>     end subroutine test
> end module module1
> program main
>   use module1
>   type(myType) :: variable
>   variable%ptr => test
> end program main

I thought that the interface would have to be ABSTRACT in this example,
as there is no subroutine MYPROC ...?

> This one also compiles and runs with the NAG compiler. It adds another
> warning message, as import is also an f2003 feature.

It also compiles with gfortran 4.5.0.  (with and without ABSTRACT)

> Speaking of ordering, I think you ought to be able to swap the order of
> the interface block and the type declaration in this code, but NAG
> doesn't like it when I do that. It says
> 
>   Cannot IMPORT MYTYPE from host MYTYPE_MODULE - it does not exist
> 
> presumably because the definition of mytype is later in the code. I
> think this is a bug, but it does require slightly careful reading to
> conclude that and I'm not 100% sure. Maybe I'll send it to NAG and see
> what Malcolm says.

For the record: gfortran 4.5.0 also complains.  I don't have a recent
4.6 installed to check whether it works in the current version.

-- Wolfgang

-- 
E-mail: firstnameinitial.lastname@domain.de
Domain: yahoo
0
Reply Wolfgang 10/29/2010 5:44:34 PM

Wolfgang Kilian <seesig@domain.invalid> wrote:

> On 10/29/2010 07:03 PM, Richard Maine wrote:
> > module myType_module
> >   type myType
> >     procedure(myproc), pointer, nopass :: ptr
> >   end type myType
> >   interface
> >     subroutine myproc(a)
> >       import myType
> >       type(myType), intent(inout) :: a
> >     end subroutine myproc
> >   end interface
> > end module myType_module
> > module module1
> >   use myType_module
> >   contains
> >     subroutine test(a)
> >       type(myType), intent(inout) :: a
> >     end subroutine test
> > end module module1
> > program main
> >   use module1
> >   type(myType) :: variable
> >   variable%ptr => test
> > end program main
> 
> I thought that the interface would have to be ABSTRACT in this example,
> as there is no subroutine MYPROC ...?

Oops. You are correct. That's what I had in mind. I see why it compiles
anyway, though it doesn't mean quite what I had intended. Add that as
another f2003 feature to the list of ones this code needs.

Without the ABSTRACT, it is still valid code for part of a program, but
it specifies the interface of an external procedure named myproc. Since
that external procedure never ends up getting referenced, the linker
doesn't bitch about not finding it. I think it still counts as being
nonconforming because the external procedure doesn't exist, but it is
not a nonconformance that the processor is required to be able to
diagnose. Of course, the compiler can't diagnose it (for traditional
compiler implementations), but a linker might be able to. 

It is probably something like having an EXTERNAL statement for a
procedure that doesn't exist. On some compilers, that might generate a
reference that causes the linker to "want" such a procedure. There is an
f77 interpretation that even suggests an implementation could use this
to include block data program units from a library (a frequent "gotcha"
in using block data), but nothing in the standard mandates such an
implementation.

-- 
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
0
Reply nospam 10/29/2010 7:52:26 PM

On Oct 29, 5:52=A0pm, nos...@see.signature (Richard Maine) wrote:
> Wolfgang Kilian <see...@domain.invalid> wrote:
> > On 10/29/2010 07:03 PM, Richard Maine wrote:
> > > module myType_module
> > > =A0 type myType
> > > =A0 =A0 procedure(myproc), pointer, nopass :: ptr
> > > =A0 end type myType
> > > =A0 interface
> > > =A0 =A0 subroutine myproc(a)
> > > =A0 =A0 =A0 import myType
> > > =A0 =A0 =A0 type(myType), intent(inout) :: a
> > > =A0 =A0 end subroutine myproc
> > > =A0 end interface
> > > end module myType_module
> > > module module1
> > > =A0 use myType_module
> > > =A0 contains
> > > =A0 =A0 subroutine test(a)
> > > =A0 =A0 =A0 type(myType), intent(inout) :: a
> > > =A0 =A0 end subroutine test
> > > end module module1
> > > program main
> > > =A0 use module1
> > > =A0 type(myType) :: variable
> > > =A0 variable%ptr =3D> test
> > > end program main
>
> > I thought that the interface would have to be ABSTRACT in this example,
> > as there is no subroutine MYPROC ...?
>
> Oops. You are correct. That's what I had in mind. I see why it compiles
> anyway, though it doesn't mean quite what I had intended. Add that as
> another f2003 feature to the list of ones this code needs.
>
> Without the ABSTRACT, it is still valid code for part of a program, but
> it specifies the interface of an external procedure named myproc. Since
> that external procedure never ends up getting referenced, the linker
> doesn't bitch about not finding it. I think it still counts as being
> nonconforming because the external procedure doesn't exist, but it is
> not a nonconformance that the processor is required to be able to
> diagnose. Of course, the compiler can't diagnose it (for traditional
> compiler implementations), but a linker might be able to.
>
> It is probably something like having an EXTERNAL statement for a
> procedure that doesn't exist. On some compilers, that might generate a
> reference that causes the linker to "want" such a procedure. There is an
> f77 interpretation that even suggests an implementation could use this
> to include block data program units from a library (a frequent "gotcha"
> in using block data), but nothing in the standard mandates such an
> implementation.
>
> --
> Richard Maine =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| Good judgment come=
s from experience;
> email: last name at domain . net | experience comes from bad judgment.
> domain: summertriangle =A0 =A0 =A0 =A0 =A0 | =A0-- Mark Twain

All right, that will do the magic.

I was very frustrated because I could easily tell how to implement
this in C++ but was not able to find a way to do it in Fortran.

Thank you very much for the clarifications, great job.
0
Reply Felipe 10/29/2010 8:41:22 PM

Wolfgang Kilian <seesig@domain.invalid> wrote:

> On 10/29/2010 07:03 PM, Richard Maine wrote:
[code elided]
>
> > Speaking of ordering, I think you ought to be able to swap the order of
> > the interface block and the type declaration in this code, but NAG
> > doesn't like it when I do that. It says
> > 
> >   Cannot IMPORT MYTYPE from host MYTYPE_MODULE - it does not exist
> > 
> > presumably because the definition of mytype is later in the code. I
> > think this is a bug, but it does require slightly careful reading to
> > conclude that and I'm not 100% sure. Maybe I'll send it to NAG and see
> > what Malcolm says.
> 
> For the record: gfortran 4.5.0 also complains.  I don't have a recent
> 4.6 installed to check whether it works in the current version.

In a separate thread, James Van Buskirk pointed out the ordering
requirement that I had missed in the standard. So I agree that NAG and
gfortran are justified in bitching. (And I wish I hadn't been quite so
prompt in firing off a bug report to NAG. Had to write back and tell
them they could mark it as resolved.)

-- 
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
0
Reply nospam 10/29/2010 11:17:12 PM

5 Replies
331 Views

(page loaded in 0.092 seconds)

Similiar Articles:













7/26/2012 11:43:29 AM


Reply: