From: burow@dxcern.cern.ch (Burkhard Burow)
Subject: Re: functions as arguments in DEC C
Organization: CERN European Laboratory for Particle Physics
Date: Sun, 24 Jan 1993 09:49:45 GMT


In article <1jshf6INNgce@gap.caltech.edu>, carl@SOL1.GPS.CALTECH.EDU (Carl J Lydick) writes:
>In article <1993Jan23.211019.6955@dxcern.cern.ch>, burow@dxcern.cern.ch (Burkhard Burow) writes:
>=My application generates 'wrapper' routines which pass along functions to
>=other routines. The wrapper routines do not know the type of the functions they
>=are passing along.
>=
>=Simplified e.g.
>=
>=void q ( int (*c)() );     /* A. prototype of q                              */
>=
>=void __q( void ( *a)() )   /* B. function with a function as argument        */
>={
>=q( a );                    /* C. pass the function parameter on to q.        */
>=}
>=
>=For which the C compiler complains:
>=
>=q( a );
>=^
>=%CC-E-PASNOTREFCOM, In this statement, the referenced type of the pointer value
>="a" is "Function (...) returning void", which is not compatible with "Function (
>=...) returning signed int".
>=at line number 5
>=
>=
>=Silicon Graphics 2.0.1 ANSI generates a similar warning, but can be satisfied
>=by casting 'a' in line B. as follows:
>=
>=q( *(void **)&a );        
>
>Well, if you want to cast a as a signed int (which is what the error message
>told you, and your declaration implies, the function q requires as an argument),
>you don't use "*(void **) &a", you use "*(int **) &a".  Have you tried that?

Yes, that of course does work. It doesn't help me though.
I guess I wasn't clear enough in my original posting.

My intermediate 'wrapper' functions know nothing about the functions they
receive as arguments and pass on to other functions.
That's why I need a cast for saying: 
 'This is a pointer to a function.
  I don't give a flying f*** about the type of argument the function returns.'

Just like one can use (void *) to say:
 'This is a pointer to an object.
  I don't give a flying f*** about the type of object.'

For the curious, the application is my cfortran.h header file which helps
make mixing C and Fortran as painless as possible.
[cfortran.h is available via anon. ftp at zebra.desy.de.]

e.g. To create a Fortran callable qsort(3C) called FQSORT, 
     compile the following 3 line program.

#include <stdlib.h>      /* qsort() prototype */
#include "cfortran.h"
FCALLSCSUB4(qsort,FQSORT,fqsort,PVOID,INT,INT,ROUTINE)

cfortran.h provides the macro definitions which convert FCALLSCSUB4()
into the (OS/compiler dependant) Fortran callable routine FQSORT.

In FCALLSCSUB4() one simply says that the 4th argument is a routine.
i.e. There's no need to specify what type is returned by the routine.

         EXCEPT SO FAR FOR DEC C, WHICH I CAN'T CONVINCE, 
         BUT I'M HOPING SOMEONE OUT THERE CAN TELL ME HOW.

Of course, one could leave out '#include <stdlib.h>' in order to get
the above to compile under DEC C, but that's hardly in the ANSI C spirit.


The above trouble, and an even sillier problem with IBM's RS/6000 C compiler,
have got me 1/2 worried that newer versions of other compilers might also
include bogus errors and warnings.
With all this progress, I'll be left longing for the good ol' days, 
when C let you do what you wanted to, without jumping through hoops.

A plea to compiler writers:
  Don't force programmers to obey your interpretation of ANSI C.
  Please provide #pragmas so that I can turn off/on an individual check
  around code which is OK.

thanks,