Sophie

Sophie

distrib > Mandriva > 2011.0 > x86_64 > by-pkgid > f13f137693327172bf7ba9b443ff3a61 > files > 357

gcc-gfortran-4.6.1-2.x86_64.rpm

<html lang="en">
<head>
<title>Working with Pointers - The GNU Fortran Compiler</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="The GNU Fortran Compiler">
<meta name="generator" content="makeinfo 4.13">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Interoperability-with-C.html#Interoperability-with-C" title="Interoperability with C">
<link rel="prev" href="Interoperable-Subroutines-and-Functions.html#Interoperable-Subroutines-and-Functions" title="Interoperable Subroutines and Functions">
<link rel="next" href="Further-Interoperability-of-Fortran-with-C.html#Further-Interoperability-of-Fortran-with-C" title="Further Interoperability of Fortran with C">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<!--
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``Funding Free Software'', the Front-Cover
Texts being (a) (see below), and with the Back-Cover Texts being (b)
(see below).  A copy of the license is included in the section entitled
``GNU Free Documentation License''.

(a) The FSF's Front-Cover Text is:

     A GNU Manual

(b) The FSF's Back-Cover Text is:

     You have freedom to copy and modify this GNU Manual, like GNU
     software.  Copies published by the Free Software Foundation raise
     funds for GNU development.-->
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
  pre.display { font-family:inherit }
  pre.format  { font-family:inherit }
  pre.smalldisplay { font-family:inherit; font-size:smaller }
  pre.smallformat  { font-family:inherit; font-size:smaller }
  pre.smallexample { font-size:smaller }
  pre.smalllisp    { font-size:smaller }
  span.sc    { font-variant:small-caps }
  span.roman { font-family:serif; font-weight:normal; } 
  span.sansserif { font-family:sans-serif; font-weight:normal; } 
--></style>
</head>
<body>
<div class="node">
<a name="Working-with-Pointers"></a>
<p>
Next:&nbsp;<a rel="next" accesskey="n" href="Further-Interoperability-of-Fortran-with-C.html#Further-Interoperability-of-Fortran-with-C">Further Interoperability of Fortran with C</a>,
Previous:&nbsp;<a rel="previous" accesskey="p" href="Interoperable-Subroutines-and-Functions.html#Interoperable-Subroutines-and-Functions">Interoperable Subroutines and Functions</a>,
Up:&nbsp;<a rel="up" accesskey="u" href="Interoperability-with-C.html#Interoperability-with-C">Interoperability with C</a>
<hr>
</div>

<h4 class="subsection">7.1.5 Working with Pointers</h4>

<p>C pointers are represented in Fortran via the special opaque derived type
<code>type(c_ptr)</code> (with private components).  Thus one needs to
use intrinsic conversion procedures to convert from or to C pointers. 
For example,

<pre class="smallexample">       use iso_c_binding
       type(c_ptr) :: cptr1, cptr2
       integer, target :: array(7), scalar
       integer, pointer :: pa(:), ps
       cptr1 = c_loc(array(1)) ! The programmer needs to ensure that the
                               ! array is contiguous if required by the C
                               ! procedure
       cptr2 = c_loc(scalar)
       call c_f_pointer(cptr2, ps)
       call c_f_pointer(cptr2, pa, shape=[7])
</pre>
   <p>When converting C to Fortran arrays, the one-dimensional <code>SHAPE</code> argument
has to be passed.

   <p>If a pointer is a dummy-argument of an interoperable procedure, it usually
has to be declared using the <code>VALUE</code> attribute.  <code>void*</code>
matches <code>TYPE(C_PTR), VALUE</code>, while <code>TYPE(C_PTR)</code> alone
matches <code>void**</code>.

   <p>Procedure pointers are handled analogously to pointers; the C type is
<code>TYPE(C_FUNPTR)</code> and the intrinsic conversion procedures are
<code>C_F_PROCPOINTER</code> and <code>C_FUNLOC</code>.

   <p>Let's consider two examples of actually passing a procedure pointer from
C to Fortran and vice versa.  Note that these examples are also very
similar to passing ordinary pointers between both languages. 
First, consider this code in C:

<pre class="smallexample">     /* Procedure implemented in Fortran.  */
     void get_values (void (*)(double));
     
     /* Call-back routine we want called from Fortran.  */
     void
     print_it (double x)
     {
       printf ("Number is %f.\n", x);
     }
     
     /* Call Fortran routine and pass call-back to it.  */
     void
     foobar ()
     {
       get_values (&amp;print_it);
     }
</pre>
   <p>A matching implementation for <code>get_values</code> in Fortran, that correctly
receives the procedure pointer from C and is able to call it, is given
in the following <code>MODULE</code>:

<pre class="smallexample">     MODULE m
       IMPLICIT NONE
     
       ! Define interface of call-back routine.
       ABSTRACT INTERFACE
         SUBROUTINE callback (x)
           USE, INTRINSIC :: ISO_C_BINDING
           REAL(KIND=C_DOUBLE), INTENT(IN), VALUE :: x
         END SUBROUTINE callback
       END INTERFACE
     
     CONTAINS
     
       ! Define C-bound procedure.
       SUBROUTINE get_values (cproc) BIND(C)
         USE, INTRINSIC :: ISO_C_BINDING
         TYPE(C_FUNPTR), INTENT(IN), VALUE :: cproc
     
         PROCEDURE(callback), POINTER :: proc
     
         ! Convert C to Fortran procedure pointer.
         CALL C_F_PROCPOINTER (cproc, proc)
     
         ! Call it.
         CALL proc (1.0_C_DOUBLE)
         CALL proc (-42.0_C_DOUBLE)
         CALL proc (18.12_C_DOUBLE)
       END SUBROUTINE get_values
     
     END MODULE m
</pre>
   <p>Next, we want to call a C routine that expects a procedure pointer argument
and pass it a Fortran procedure (which clearly must be interoperable!). 
Again, the C function may be:

<pre class="smallexample">     int
     call_it (int (*func)(int), int arg)
     {
       return func (arg);
     }
</pre>
   <p>It can be used as in the following Fortran code:

<pre class="smallexample">     MODULE m
       USE, INTRINSIC :: ISO_C_BINDING
       IMPLICIT NONE
     
       ! Define interface of C function.
       INTERFACE
         INTEGER(KIND=C_INT) FUNCTION call_it (func, arg) BIND(C)
           USE, INTRINSIC :: ISO_C_BINDING
           TYPE(C_FUNPTR), INTENT(IN), VALUE :: func
           INTEGER(KIND=C_INT), INTENT(IN), VALUE :: arg
         END FUNCTION call_it
       END INTERFACE
     
     CONTAINS
     
       ! Define procedure passed to C function.
       ! It must be interoperable!
       INTEGER(KIND=C_INT) FUNCTION double_it (arg) BIND(C)
         INTEGER(KIND=C_INT), INTENT(IN), VALUE :: arg
         double_it = arg + arg
       END FUNCTION double_it
     
       ! Call C function.
       SUBROUTINE foobar ()
         TYPE(C_FUNPTR) :: cproc
         INTEGER(KIND=C_INT) :: i
     
         ! Get C procedure pointer.
         cproc = C_FUNLOC (double_it)
     
         ! Use it.
         DO i = 1_C_INT, 10_C_INT
           PRINT *, call_it (cproc, i)
         END DO
       END SUBROUTINE foobar
     
     END MODULE m
</pre>
   </body></html>