why BIND not allowed for internal subroutine?

  • Follow


according to ISO/IEC SC22/JTC1/WG5/N1581, C1237a (R1225) one
is not allowed to use BIND on an internal subroutine.

ftp://ftp.nag.co.uk/sc22wg5/N1551-N1600/N1581.pdf

page 14. I did not understand too well the note below this

"C1237a (R1225) A proc-language-binding-spec shall not be
specified for a procedure defined in a sub-
module unless its interface is declared in the ancestor module."

Ok. Will do the above, but my question is: Why, and is there a
way to go around it?

Because it makes it much easier if I can write the subroutine inside
CONTAINS rather than outside, where now I have to provide an interface
for the subroutine, and also the subroutine needs an extra USE to access
the fortran openGL. It it was an internal sub, then the program USE
will be enough. Now I have to duplicate USE openGL in the main
program and in the subroutine.

It is a routine that will _only_ be called by this one main program.
I just think it fits more logically as an internal subroutine, but
I can't do that due to the BIND on it per the fortran OPEN GL spec.

Here is the program when the subroutine is internal (I am
writing small fortran programs using the fortran openGL interface
to learn it)

---------------------------------------
PROGRAM simple1
USE opengl_glut
USE opengl_gl
IMPLICIT none

CALL glutInit()
......
CALL glutDisplayFunc(display)  !-- callback to draw
CALL glutMainLoop

CONTAINS
   SUBROUTINE display() bind(c)
   implicit none

   CALL glClear(GL_COLOR_BUFFER_BIT)
   .....
   CALL glFlush()
END SUBROUTINE display

END PROGRAM simple1
-----------------------------------

And here is how it would look like with the subroutine outside:

------------------------------
SUBROUTINE display() bind(c)
USE opengl_gl
implicit none

   CALL glClear(GL_COLOR_BUFFER_BIT)
   .....
   CALL glFlush()
END SUBROUTINE display

PROGRAM simple1
USE opengl_glut
USE opengl_gl
IMPLICIT none
interface
      subroutine display() bind(c)
      end subroutine display
end interface
CALL glutInit()
......
CALL glutDisplayFunc(display)  !-- callback to draw
CALL glutMainLoop

END PROGRAM simple1
---------------------------

You can see, as internal subroutine, the program is smaller
in size and less code duplication.

I am just asking to learn, not to complain, I am a newbie
in fortran. I am sure there is a good reason for this.

thanks,
--Nasser
0
Reply Nasser 7/22/2012 6:10:19 AM

Nasser M. Abbasi wrote:
>
> according to ISO/IEC SC22/JTC1/WG5/N1581, C1237a (R1225) one
> is not allowed to use BIND on an internal subroutine.
> ftp://ftp.nag.co.uk/sc22wg5/N1551-N1600/N1581.pdf

Instead of looking at the draft Technical Report for Enhanced Module 
Facilities in Fortran, I'd recommend the Fortran 95/2003/2008 standards.

See http://www.nag.co.uk/sc22wg5/links.html and 
http://gcc.gnu.org/wiki/GFortranStandards


Actually, your program below seems to be a valid Fortran 2008 program, 
but not a valid Fortran 2003 program. Note that "display" has no C 
binding name � and Fortran 2003 also doesn't allow one:

"C1254 (R1229) A proc-language-binding-spec with a NAME= specifier shall 
not be specified in the function-stmt or subroutine-stmt of an internal 
procedure, or of an interface body for an abstract interface or a dummy 
procedure."


Fortran 2003 had:

"C1237 (R1225) A proc-language-binding-spec shall not be specified for 
an internal procedure."


Thus, depending on compilers you use, your could actually consider to 
use this Fortran 2008 feature.

[gfortran 4.3 supports Bind(C) on internal procedures as vendor 
extension and starting from 4.4 as F2008 extension (with proper 
-std=f2003/f2008 diagnostic).]


The reason that C binding was now allowed for internal procedures is the 
same as why passing any internal procedures as actual argument was not 
supported: One has to be careful regarding host-associated variable. For 
instance the following program, which should print 5 2. Here, the 
variable "j" of the first call to "foo" has to be used by "internal" � 
and not the one of the second call to "foo".

Implementing this properly is not trivial, hence, it took a while until 
the Fortran committee finally allowed it (in Fortran 2008). (gfortran 
supports it since GCC 4.6; as the compiler itself supported it, it was 
one of the simplest features to implement.)


program test
  call foo(1, .false.)
end program test

subroutine bar(f)
   procedure() :: f
   call foo(5, .true.)
   call f()
end subroutine bar

subroutine foo(i, print)
   logical :: print
   integer :: j
   j = 2*i
   if (print) then
     print *, i
   else
     call bar(internal)
   end if
contains
   subroutine internal()
     print *, j
   end subroutine internal
end


Tobias

> ---------------------------------------
> PROGRAM simple1
> USE opengl_glut
> USE opengl_gl
> IMPLICIT none
>
> CALL glutInit()
> .....
> CALL glutDisplayFunc(display)  !-- callback to draw
> CALL glutMainLoop
>
> CONTAINS
>    SUBROUTINE display() bind(c)
>    implicit none
>
>    CALL glClear(GL_COLOR_BUFFER_BIT)
>    .....
>    CALL glFlush()
> END SUBROUTINE display
>
> END PROGRAM simple1
> -----------------------------------
0
Reply burnus (564) 7/22/2012 7:42:13 AM


On 7/22/2012 2:42 AM, Tobias Burnus wrote:

>
> Actually, your program below seems to be a valid Fortran 2008 program,
> but not a valid Fortran 2003 program. Note that "display" has no C
> binding name � and Fortran 2003 also doesn't allow one

Thanks Tobias, That really helped. I did not think of trying f2008
since I am using an openGL fortran 2003 binding and was using f2003
all the time.

You are correct! It worked with f2008. I changed the code to use
an internal subroutine with bind(c) and it compiled and runs fine
now.

I'll use f2008 from now on.
Fyi, here is a complete small program to draw a line on the screen
with the compile command I use. Using version 4.6.3 on Linux 32 bit

-------------------------------
PROGRAM simple3 !-- use F2003 Fortran openGL
USE opengl_glut
USE opengl_gl
IMPLICIT none
integer :: i

CALL glutInit()
CALL glutInitDisplayMode(GLUT_SINGLE+GLUT_RGB)
CALL glutInitWindowSize( 250, 250 );
CALL glutInitWindowPosition( 200, 200 );
i =  glutCreateWindow( " simple1 " );

CALL glClearColor(0.,0.,0.,0.) !-- background color
CALL glMatrixMode(GL_PROJECTION)
CALL glLoadIdentity()
CALL glOrtho(0.0d0,1.0d0,0.0d0,1.0d0,-1.0d0,1.0d0)
	
CALL glutDisplayFunc(display)  !-- callback to draw
CALL glutMainLoop

CONTAINS
!-------------------
SUBROUTINE display() bind(c)
implicit none

CALL glClear(GL_COLOR_BUFFER_BIT)
CALL glColor3f(1.0,1.0,1.0)

call glBegin(GL_LINES);
   call glVertex3f(0.25, 0.25, 0.0)
   call glVertex3f(0.75, 0.75, 0.0)
call glEnd( );

CALL glFlush()
END SUBROUTINE display

END PROGRAM simple3
-----------------------------

command to build:

gfortran -std=f2008 -Wall simple3.f90 GLUT_fonts.o OpenGL_freeglut.o
OpenGL_glu.o OpenGL_gl.o  -L/usr/lib -lglut -lGL -lGLU -lXaw -lXt
-lXmu -lXi -lXext -lX11 -lm  -lpthread -ldl -lgfortran -o simple3

../simple3

Thanks for your help. Much better using internal subroutine. Less
code to write and more clear.

--Nasser

0
Reply Nasser 7/22/2012 8:43:13 AM

Nasser M. Abbasi <nma@12000.org> wrote:

> according to ISO/IEC SC22/JTC1/WG5/N1581, C1237a (R1225) one
> is not allowed to use BIND on an internal subroutine.

> ftp://ftp.nag.co.uk/sc22wg5/N1551-N1600/N1581.pdf

> page 14. I did not understand too well the note below this

(snip)

> Ok. Will do the above, but my question is: Why, and is there a
> way to go around it?

I believe this went away in Fortran 2008. If you are lucky enough
to have a F2003 compiler, you still might not have an F2008 compiler.

Note that, unless I remember it wrong, in F2003 you can't use
internal procedure names as actual arguments, BIND(C) or not.

If you can't use them without BIND(C), it is even less likely
with BIND(C). There is no way to call an internal procedure from C,
other than passing it, or a pointer to it, to an extenal routine.

I believe that both restrictions are gone in F2008.

Does that help? The way around is to find an F2008 compiler.

-- glen
0
Reply gah (12254) 7/22/2012 9:22:20 AM

"Nasser M. Abbasi" <nma@12000.org> wrote in message 
news:jug5ga$r06$1@speranza.aioe.org...

> And here is how it would look like with the subroutine outside:

> ------------------------------
> SUBROUTINE display() bind(c)
> USE opengl_gl
> implicit none

>   CALL glClear(GL_COLOR_BUFFER_BIT)
>   .....
>   CALL glFlush()
> END SUBROUTINE display

> PROGRAM simple1
> USE opengl_glut
> USE opengl_gl
> IMPLICIT none
> interface
>      subroutine display() bind(c)
>      end subroutine display
> end interface
> CALL glutInit()
> .....
> CALL glutDisplayFunc(display)  !-- callback to draw
> CALL glutMainLoop

> END PROGRAM simple1

Since Fortran 90, it's much more normal to put everything in modules.
Thus the normal code would be:

module OpenGL_stuff
   USE opengl_gl
   implicit none
   contains
      SUBROUTINE display() bind(c)

         CALL glClear(GL_COLOR_BUFFER_BIT)
         .....
         CALL glFlush()
      END SUBROUTINE display
end module OpenGL_stuff

PROGRAM simple1
   USE opengl_glut
   USE opengl_gl
   USE OpenGL_stuff
   IMPLICIT none
   CALL glutInit()
   .....
   CALL glutDisplayFunc(display)  !-- callback to draw
   CALL glutMainLoop

END PROGRAM simple1

Also glut is so limiting that you will grow out of it quickly.

-- 
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


0
Reply not_valid (1681) 7/22/2012 12:08:46 PM

Nasser M. Abbasi <nma@12000.org> wrote:

> page 14. I did not understand too well the note below this
> 
> "C1237a (R1225) A proc-language-binding-spec shall not be
> specified for a procedure defined in a sub-
> module unless its interface is declared in the ancestor module."
> 
> Ok. Will do the above, but my question is: Why, and is there a
> way to go around it?

Others answered the other parts of your post as well or better than I
would. But I didn't notice any response to the above.

First, note that nothing else in your posting had anything to do wih
submodules. I will take the above as an unrelated question that happened
tp occur to you. If you did think there was a relationship, then realize
that there is not; since the code you showed has no submodules, a
restriction related to what you can do in a submodule is moot.

But answering the question, I would guess (I don't recall discussion of
that particular restriction, but I think I can see why it would exist)
that this relates to the fact that a submodule is in essence an
implementation of what is described in the ancestor module. I might even
have preferred a term like "implementation module" as more descriptive
than "submodule". A proc-language-binding-spec makes a procedure
"visible" outside of the module. A submodule is not supposed to have
externally visible bits that are other than what was declared in its
ancestor module. If it had such things, that would make it more than an
implementation of what was already described. Anyway, that's what I'd
guess.

-- 
Richard Maine
email: last name at domain . net
domain: summer-triangle
0
Reply nospam47 (9742) 7/23/2012 8:48:30 AM

5 Replies
39 Views

(page loaded in 0.106 seconds)

Similiar Articles:













7/23/2012 3:38:57 PM


Reply: