Topic: Callbacks


Author: coetmeur@icdc.fr (Alain Coetmeur)
Date: 1995/05/31
Raw View
In article <3pvobj$a6t@ritz.cec.wustl.edu> jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut) writes:

I forward this important question to comp.std.c++, IMHO it seems to concern this group...
First of all we need a stright legal answer to this problem, and maybe will
it raise a small addendum in the c++ draft to precise this point.

talking about C qsort() - like callback usage

>   :While some compilers will allow the use of a static method or C++ function in
>   :the place where the C callback is expected, this is undefined behaviour.
>
>   Can you cite chapter and verse of the draft standard to prove this assertion?
>   I haven't found anything to suggest that this is true.  This passage from
>   [7.5] says "Taking the address of a function whose linkage is other than
>   C++ or C produces undefined behavior."
>
>   Are you aware of any compilers that don't allow this?

Someone in this thread talked about Zortech C++ where C++ and C functions calls
 where incompatible.

> I was under the
>   impression that the only difference between the C and C++ calling
>   conventions was name mangling and since mangling has no effect on taking
>   the address of a function, passing a C++ function pointer to a C function
>   should be safe even if it is not declared as extern "C".
>
>   :You *must* declare the callback as extern "C" and thus you *cannot* use a static
>   :method - though you can call from the extern "C" stub into one.
>   :
>   :James

 Maybe is James right, but IMHO it would'nt be good for the standard...
 follow my arguments below.

>   Stephen Gevers
>   sg3235@shelob.sbc.com


 Anyway i have some idea, follow my tracks:

extern "C" function are necessary to declare/define function that
are defined/declared in a "compatible" C compiler... Not all "C" compiler
should be compatible, but an implementor should support one, for practical
reasons... If there is no C compiler supported, then there is no "C"-callback
compatibility problem. So I suppose there is one !

in c++ the folowings are true (i think):

1- there is no way to differentiate the following pointer to function
having the same parameters and returns:
 a- a c++  function
 b- a c++ class member function
 c- an extern "C" function

2- the semantic of the call of a  function via a pointer is well defined

thus calling a "C" function or a c++ function/class member via a pointer
have the same semantic IN C++...
thus if you write "qsort()" in C++ (as extern "C" anyway)
it must work with C like good old "qsort()"
so, if you rewrite all C library in C++, it would be C link compatible.

this is a progress, but not the solution because:

what about if qsort is written in "C" ...
if it does not work, it mean that a function pointer in C++ can make a difference
between C++ and C function address and call them differently at runtime, unlike
a dumb C function !
even worse, giving a function pointer to a dumb-C function could only be done for
pointer to dumb-C function. worst of all, because you can return
 a pointer to function from a
dumb-C function, then the dumb-C function pointer
 must have the same binary value in C and C++,
anyway beeing different from  C++-function pointer in the same memory space.

feasible, but what a mess... is it useful ? I think no, but maybe ... who knows?

At least should C++ standard be clear on this point !

Either:
Any pointer to C++ function, C++ class member function or  extern "C" function can
be safely used as a parameter of an extern "C" function implemented in C++ or C.
[ my preference ]

Or:
Using a pointer to C++ function or C++ class member as a parameter to a
function implemented in "C" have undefined results...
[ a mess ]

To go further and justify the need to enforce the "pointer" compatibility
while ensuring calling convention variety, here are a few ideas and reflexions:

A problem  arise if Calling convention are not compatible...
there are such a problem with microsoft C/C++ between :
PASCAL calling convention (stack parameters freed by callee)
C calling convention   (stack parameters freed by caller)
FAST      (register used for speed)
... and so on

what have been microsoft choice ? in fact
the parameter passing convention is in the signature of the function, and
in the signature of the pointer, marked by some modifiers :
example:  void __pascal (*ptr_to_pascal_func)();
   void __cdecl (*ptr_to_c_func)();
   void __fastcall (*ptr_to_fast_func)();

so I think that no useful behavior can be offered by refusing pointer
to any function compatibility straight away. If incompatibility must be
checked, modifiers should be used to mark this in the signature...

for example "qsort()" could force the "compare" pointer to function to be,
say __fastcall, but it should be possible to declare a c++
class member function to be "__fastcall" and thus use it with qsort()...

moreover it would be "nice" if the implementor ensure that the default
C++ (and extern "C" in C++) calling convention is also the usual C
calling convention ...


--
=============================================================
coetmeur@icdc.fr (Alain Coetmeur, Informatique-CDC R&D dept.)
[Dislaimer: Opinions expressed here are my own... ]