title: Holding a pointer to a C function inside a Fortran derived type
body: <p>I have a Fortran DLL which is called from a C program, and one of my procedures needs periodically to call a callback function which is supplied by the C program. I currently have it working well in its 'simple' form, but I'd like to be able to store my callback pointer inside a derived type, so that it can be passed around within my Fortran code more easily. So far, nothing I've tried seems to work.</p>
  
  <p>To begin with, here is what I have at the moment, and this <em>does</em> work:</p>
  
  <p>Starting in the C (OK, actually C++) program, the header prototype for the callback is:</p>
  
  <pre><code>typedef void (*fcb)(void *)
  </code></pre>
  
  <p>and the prototype for the Fortran call is:</p>
  
  <pre><code>extern "C" __declspec(dllexport) int fortran_function(int n,
                                                        uchar *image_buffer,
                                                        fcb callback,
                                                        void *object);
  </code></pre>
  
  <p>The actual callback function is:</p>
  
  <pre><code>void callback(void* pObject)
  {
      // Cast the void pointer back to the appropriate class type:
      MyClass *pMyObject = static_cast&lt;MyClass *&gt;(pObject);
      pMyObject -&gt; updateImageInGUI();
  }
  </code></pre>
  
  <p>and the call to the Fortran code from C++ is:</p>
  
  <pre><code>int error = fortran_function(m_image.size(), m_image.data, callback, this);
  </code></pre>
  
  <p>where <code>m_image</code> is an array of image data which is a member attribute of the current object. What happens is that the C++ passes the raw image data to the Fortran DLL and asks the Fortran to process it, and since this takes a long time the Fortran periodically updates the image buffer and calls the callback to refresh the GUI. Anyway, moving on to the Fortran side, we define an interface for the C callback:</p>
  
  <pre><code>abstract interface
      subroutine c_callback(c_object) bind(c)   
          use, intrinsic :: iso_c_binding
          type(c_ptr), intent(in) :: c_object     
      end subroutine c_callback
  end interface
  </code></pre>
  
  <p>and define our main Fortran routine thus:</p>
  
  <pre><code>integer(c_int) fortran_function(n, image, callback, c_object)     &amp;
                                  bind(c, name='fortran_function')
  
      integer(c_int), value :: n
      integer(4), intent(inout), dimension(n) :: image
      procedure(c_callback) :: callback
      type(c_ptr), intent(in) :: c_object
  </code></pre>
  
  <p>Somewhere in the main routine we call our subroutine, <code>foo</code>:</p>
  
  <pre><code>call foo(data, callback, c_object)
  </code></pre>
  
  <p>...where <code>foo</code> is defined as:</p>
  
  <pre><code>subroutine foo(data, callback, c_object)
  
      type(my_type), intent(inout) :: data
      procedure(c_callback) :: callback
      type(c_ptr), intent(in) :: c_object
      ...
      call callback(c_object)
      ...
  end function foo
  </code></pre>
  
  <p>As I said, all of this works well and has done so for a long time.</p>
  
  <p>Now for the things I've tried but which don't work:</p>
  
  <p><strong>The naive approach, just copying the arguments into the fields of a structure</strong></p>
  
  <p>I'd expect this to work, since all all I'm doing is to copy the original elements into a structure with no modification. Nothing changes on the C side, nor in the definition of the main Fortran function nor the abstract interface to <code>c_callback</code>. All I do is to create a new Fortran derived type:</p>
  
  <pre><code>type :: callback_data
      procedure(c_callback), pointer, nopass :: callback =&gt; null()
      type(c_ptr) :: c_object
  end type callback_data
  </code></pre>
  
  <p>and then in my main function I populate this with the values received from the C application:</p>
  
  <pre><code>data%callback_data%callback =&gt; callback
  data%callback_data%c_object = c_object
  call foo(data)
  </code></pre>
  
  <p>The subroutine foo has been slightly modified so that it now looks for the callback and C object within the structure:</p>
  
  <pre><code>subroutine foo(data)
      type(my_augmented_type), intent(inout) :: data
      ...
      call data%callback_data%callback(data%callback_data%c_object)
      ...
  end function foo
  </code></pre>
  
  <p>This fails at the call with an "access violation reading location 0xffffffffffffffff". </p>
  
  <p><strong>The sophisticated approach using more of the iso_c_binding features</strong></p>
  
  <p>Again nothing changes on the C side but I modify the Fortran side of the main function to receive the callback as a <code>c_funptr</code>:</p>
  
  <pre><code>integer(c_int) fortran_function(n, image, callback, c_object)     &amp;
                                  bind(c, name='fortran_function')
  
      integer(c_int), value :: n
      integer(4), intent(inout), dimension(n) :: image
      type(c_funptr), intent(in) :: callback
      type(c_ptr), intent(in) :: c_object
  </code></pre>
  
  <p>I define the abstract interface to <code>subroutine c_callback</code> just as before, though I've experimented both with leaving the <code>bind(c)</code> part of it in, and omitting it. The code within the main function that calls the subroutine <code>foo</code> is now:</p>
  
  <pre><code>call c_f_procpointer(callback, data%callback_data%callback)
  data%callback_data%c_object = c_object
  call foo(data)
  </code></pre>
  
  <p>...with the subroutine foo itself still defined as in the previous example.</p>
  
  <p>Unfortunately this fails in exactly the same way as the previous example.</p>
  
  <p>I assume that there is a correct syntax to achieve what I'm trying to achieve here, and I'd be very grateful for any advice.</p>