Re: C++ Draw Callback?

New Message Reply Date view Thread view Subject view Author view

Hansong Zhang (zhangh++at++cs.unc.edu)
Fri, 6 Dec 1996 22:56:42 -0500 (EST)


Chris Volpe wrote:
>
> Hansong Zhang wrote:
> >
> >
> > The same thing can be done to non-static member functions, also.
> > But you need a explicit type conversion:
> >
> > chan->setTravFunc( PFTRAV_DRAW, (pfChanFuncType)MyClass::DrawChannel );
> >
> > You'll still get an warning about this conversion, but you could
> > ignore that...
>
> No you can't. Non-static member functions have a "this" pointer passed
> in behind the scenes as part of the calling convention. If you try to
> invoke the member function as if it were an ordinary function, it will
> crash immediately if you're lucky, and deceptively appear to work, for
> now, if you're unlucky. What will likely happen is that your member
> function will think that the pfChannel* parameter passed in by performer
> is actually the this-pointer, and will think that the void* parameter
> passed in is atually the pfChannel* parameter, leaving the void*
> parameter undefined within the member function, and it all goes downhill
> from there...
>
Good point. I examined my code and realized why the hack worked for
me. But, a forced type conversion CAN work properly, and it's needed
when a callback function *cannot* be static for some reason. Here's a report
of what I got, for anybody interested...

I have a global function table of member functions,

functype FuncTable[64] = {
    ...
    (functype)MyClass::draw_for_a_specific_attribute_binding;
    ...
}

And in another member function of the same class, I select a function from
the function table and call it:

MyClass::Draw(...) {
    ...
    FuncTable[Index](); // note: this function has no argument
}

When MyClass::Draw() is called, the calling stack is like:

stack ptr + 0 | THIS pointer |
stack ptr + 4 | int index |
....

And after entering function FuncTable[Index](), THE STACK REMAINS THE SAME
and the this pointer is still on top of stack, which is happily used by
draw_for_a_specific.. function!

So for it to work two conditions must be satisfied:
a) the compiler doesn't put any other implicit parameter in calling stack
   frame (e.g. the return address as they normally have in the stack on PCs).
b) The called function (i.e. functions suffering from the forced type
   conversion) should have any arguments.

Now, the *correct* way to do it is to pass the "this" pointer explicitly.
i.e. for a variable FuncPtr defined and init'd as:

functype FuncPtr = (functype) MyClass::memberFunc;

we should call it as: FuncPtr(objectPtr, other_arguments);
- sure we are assuming the compiler places the "this" pointer as the 1st arg,
  which is true for the AT&T cfront and sgi's integrated CC.

but the performer traversal master function doesn't pass an explicit
"this". As Bernard pointed out, we can subclass pfChannel.

Hansong
-------------------------------------------------------------
Hansong Zhang \ zhangh++at++cs.unc.edu
Walkthrough Group \ http://www.cs.unc.edu/~zhangh
Department of Computer Science \ (919)962-1835 (O)
UNC-Chapel Hill \ (919)914-3973 (H)

"I create abstract systems from pure information, Albert. I'm
a *programmer*... Quantum nonlocality is a bug." -- God
-------------------------------------------------------------
=======================================================================
List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/
            Submissions: info-performer++at++sgi.com
        Admin. requests: info-performer-request++at++sgi.com


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:54:06 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.