Re: legality of signature changes of callback functions



Eric Sosman wrote:
regis wrote:
Hello,

Suppose that some type of callback function is declared
to take a pointer to some struct as one of its argument.

Is it legal to implement the callback functions as
taking a void* for this argument.

No. (Usually the question is asked the other way
around, but the answer is still No.)

Reason: If you call a function via a function pointer
whose type does not match that of the called function,
the behavior is undefined.

Rationale: The caller builds an argument list that
matches the caller's idea of what the called function
expects to receive. If the called function expects one
thing and the caller has set things up differently, it's
anybody's guess what might happen.

Practicality: On many machines it will turn out that
"all pointers smell the same," meaning that they have the
same representation and are passed to functions by the
same conventions. So you're likely to get away with it --
until, in the words of the Sixth Commandment, "the day
before thy Thesis Oral or thy Big Pitch To The Client."

ok, thank you.

(The context is that I am sometimes fed up
with all those casts in gtk and I wonder if it is
legal to replace GtkWidget* arguments of callback functions
by void* directly in the signature of the callbacks)

I'm not familiar with GTK, but this seems backwards:
Something in GTK passes one of your functions a GtkWidget*,
and you want to transform this to a void*? That is, you
want to throw away the information about the type of the
thing it points to? Sounds bizarre: More commonly, one
receives a void* from a type-ignorant caller, and then
converts it to a Something* to add type information. It's
not so usual to want to destroy type information, so I sort
of wonder what you're up to ...

I wanted to avoid to constantly cast pointers
to match the signature of the functions called inside the callback:

for example, given...

typedef struct { ... } Foo1;
typedef struct { Foo1 foo1; ...} Foo2;
typedef struct { Foo2 foo2; ...} Foo3;
typedef void (* Callback2) (Foo2*, void*)

void some_function1 (Foo1 * f);
void some_function2 (Foo2 * f);
void some_function3 (Foo3 * f);

.... a callback will typically have to downcast or upcast
its argument to functions called inside it:

void some_callback2 (Foo2 * f, void * data) {
some_function2 ( f);
some_function1 ((Foo1*) f); /* upcast needed */
some_function3 ((Foo3*) f); /* downcast needed */
}

.....So, the first step was to re-write it as:

void some_callback2 (Foo2 * f, void * data) {
void * v= f;
some_function2 (v);
some_function1 (v); /* no upcast needed */
some_function3 (v); /* no downcast needed */
}

.... and I wondered if I could re-re-write it directly as:

void callback (void * f, void * data) {
some_function2 (f);
some_function1 (f);
some_function3 (f);
}

.... but obviously, I can't do this last step,
because your answer was that it was a constraint violation.

--
regis










.



Relevant Pages

  • Re: [RFC] timers, pointers to functions and type safety
    ... * they have callback of type void ... callback is called by the code that even in theory has no ... cast to unsigned long and cast back in the callback. ... number - not a pointer cast to unsigned long, not an index in array, etc. ...
    (Linux-Kernel)
  • Re: function pointer help!
    ... //the return void and input prameters are defined in the manual... ... void MyProjectView::CallHandler(int,unsigned int, unsigned int, void*) ... You are attempting to use a C++ member function as the callback, but the callback is defined in terms or C, not C++. ... The underlying problem is that C++ functions receive a hidden parameter, the 'this' pointer, so their signature is incompatible with C definitions. ...
    (microsoft.public.vc.mfc)
  • Re: Global restricted function pointer
    ... void; ... I _can_ declare a global restricted object pointer, ... And even if it did, you do *not* want it optimized into a register, ... I.E. each callback returns the next callback instead of ...
    (comp.lang.c)
  • Re: Custom filter
    ... You expect a function pointer so better be safe and tell the ... STDMETHODIMP CPrintPressFilter::Setcallback(void* Callback) ... public delegate void MyCallback; ...
    (microsoft.public.win32.programmer.directx.video)
  • Re: [PATCH 04/10][RFC] tracing: Remove per event trace registering
    ... Well, one thing, the callback is not going to be the same as the ... void mycallback; ... I also don't trust that these complex TRACE_EVENTpreprocessor macros ... I use "proto" to make the tracepoint and the callback, ...
    (Linux-Kernel)