On 2016-01-20 12:23-0000 Arjen Markus wrote:

> As for your idea for diambiguation: that ought to work, I think. I will have 
> a close look at that aspect.

Here is the code I used to implement my idea:
     ...
     interface plstransform
         module procedure plstransform_impl
     end interface plstransform
     private :: plstransform_impl
     ...
contains
...
subroutine plstransform_impl( proc_single, proc_data_single, proc_double, 
proc_data_double, data )
     procedure(pltransform_proc_single), optional :: proc_single
     procedure(pltransform_proc_data_single), optional :: proc_data_single
     procedure(pltransform_proc_double), optional :: proc_double
     procedure(pltransform_proc_data_double), optional :: proc_data_double
     type(c_ptr), optional, intent(in) :: data
     interface
         subroutine interface_plstransform( proc, data ) bind(c, name = 
'c_plstransform' )
             import :: c_funptr, c_ptr
             type(c_funptr), value, intent(in) :: proc
             type(c_ptr), value, intent(in) :: data
         end subroutine interface_plstransform
      end interface

      if( .not. present(proc_single) .and. .not. present(proc_data_single) &
          .and. .not. present(proc_double) .and. .not. 
present(proc_data_double) &
           .and. .not. present(data) ) then
         call interface_plstransform( c_null_funptr, c_null_ptr )
      elseif( present(proc_single) .and. .not. present(proc_data_single) &
           .and. .not. present(proc_double) .and. .not. 
present(proc_data_double) &
           .and. .not. present(data) ) then
            pltransform_single => proc_single
            call interface_plstransform( c_funloc(pltransformf2c_single), 
c_null_ptr )
      elseif( .not. present(proc_single) .and. present(proc_data_single) &
           .and. .not. present(proc_double) .and. .not. 
present(proc_data_double) &
           .and. present(data) )then
            pltransform_data_single => proc_data_single
            call interface_plstransform( c_funloc(pltransformf2c_data_single), 
data )
      elseif( .not. present(proc_single) .and. .not. present(proc_data_single) &
           .and. present(proc_double) .and. .not. present(proc_data_double) &
           .and. .not. present(data) ) then
            pltransform_double => proc_double
            call interface_plstransform( c_funloc(pltransformf2c_double), 
c_null_ptr )
      elseif( .not. present(proc_single) .and. .not. present(proc_data_single) &
           .and. .not. present(proc_double) .and. present(proc_data_double) &
           .and. present(data) ) then
            pltransform_data_double => proc_data_double
            call interface_plstransform( c_funloc(pltransformf2c_data_double), 
data )
      else
         write(error_unit,"(a)") "f95 plstransform ERROR: one of the following 
valid argument choices not used:"
         write(error_unit,"(a)") "(1) no arguments;"
         write(error_unit,"(a)") "(2) a single-precision coordinate_transform 
callback;"
         write(error_unit,"(a)") "(3) a single-precision coordinate_transform 
callback and c_loc of defined data type;"
         write(error_unit,"(a)") "(4) a double-precision coordinate_transform 
callback; or"
         write(error_unit,"(a)") "(5) a double-precision coordinate_transform 
callback and c_loc of defined data type."
         return
      endif
end subroutine plstransform_impl
...

I was pretty proud of that implementation, but there is a "slight" problem
with it which is it does not work!  :-(

After doing some experiments commenting out certain parts it turns
out that gfortran (and I assume all other Fortran compilers) treats the first
four arguments as completely interchangeable as far as disambiguation
is concerned.  So the library builds OK based on the disambiguation
between 0, 1, 2, 3, and 4 callbacks in the argument list, but when
an example specifies just one callback, the first of the possibilities
is selected which of course does not match in type (because our examples
currently use just double-precision callbacks.  Even if I comment
out all the single types, gfortran still cannot disambiguate
between proc_double and proc_data_double, and apparently just
assumes the first because under those conditions example 19 (which
does not use the data form of callback) compiles OK, but example 22
(which does use the data form) fails to compile with the message

/home/software/plplot/HEAD/plplot.git/examples/f95/x22f.f90:232.56:

          call plstransform( transform_data, c_loc(data))
                                                         1
Error: There is no specific subroutine for the generic 'plstransform' at (1)

This is really peculiar behaviour that I have alluded to before.
Clearly, the gfortran compiler enforces the rule that the callback
function arguments supplied by the calling routine must match exactly
in number and type with what is expected by the library, but that
compiler refuses to use that known information to disambiguate.  So
for this particular case we use the presence or absence of data in the
argument list to disambiguate (i.e., we use the method presently
implemented on master tip).

So the question is whether this peculiar behaviour is due to a
gfortran bug or due to an issue with the Fortran standard for
disambiguation, and I hope you will continue to pursue that question
with your Fortran contacts.

Meanwhile, I will throw away the above "good" idea and continue with
the (double-precision only) status quo for plstransform (and
plslabelfunc).

Alan
__________________________
Alan W. Irwin

Astronomical research affiliation with Department of Physics and Astronomy,
University of Victoria (astrowww.phys.uvic.ca).

Programming affiliations with the FreeEOS equation-of-state
implementation for stellar interiors (freeeos.sf.net); the Time
Ephemerides project (timeephem.sf.net); PLplot scientific plotting
software package (plplot.sf.net); the libLASi project
(unifont.org/lasi); the Loads of Linux Links project (loll.sf.net);
and the Linux Brochure Project (lbproject.sf.net).
__________________________

Linux-powered Science
__________________________

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
_______________________________________________
Plplot-devel mailing list
Plplot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-devel

Reply via email to