[comp.lang.c++] Pointer to function

richard@ben.Jpl.Nasa.Gov (Conan the Barbarian) (03/20/90)

This is an answer to my own posting ( I did some more
digging. Yes, there is a better reference than Stroustrup,
Sun, AT&T, Hansen, and the Waite group for at least this
topic. The Complete C++ Primer by Weiskamp and Flamig is more
expansive. Though Stroustrup's book does have the information
in a cryptic non-standard segment on pointers to member functions.)
You should not pass the address of a member function to
another routine unless the routine is written to
support C++ and specifies an address to a member
function rather than the address of a function.
The method of passing the address is then moot.

Due to the implementation feature of the hidden argument(this),
C++ member function  and C calls are not actually fully compatible 
in their use.

This is not a flame. The use of the member function address
does not make sense when separated from the class instance.
(Yes I can think of a million exceptions also.)
The member function would not fully  operate as documented without
the hidden argument. 

Yuck. That means the handler for a asynchronous server can
not use C++ strategies unless you have all of the server
source also. Double yuck. Who wants to re-write X, Motif,
Xview, Sunview, etc? Triple yuck

kc@rna.UUCP (Kaare Christian) (03/21/90)

In article <1990Mar19.233906.23149@elroy.jpl.nasa.gov>, richard@ben.Jpl.Nasa.Gov (Conan the Barbarian) writes:
: This is not a flame. The use of the member function address
: does not make sense when separated from the class instance.
: (Yes I can think of a million exceptions also.)
: The member function would not fully  operate as documented without
: the hidden argument. 
: 
: Yuck. That means the handler for a asynchronous server can
: not use C++ strategies unless you have all of the server
: source also. Double yuck. Who wants to re-write X, Motif,
: Xview, Sunview, etc? Triple yuck

This is an example of a situation where friends are useful. (See 
ongoing discussion of friends.)

Kaare Christian
kc@rna.rockefeller.edu

jim@ocsmd.ocs.com (Jim Muth) (03/21/90)

In article <1990Mar19.233906.23149@elroy.jpl.nasa.gov> richard@ben.Jpl.Nasa.Gov (Conan the Barbarian) writes:

>Yuck. That means the handler for a asynchronous server can
>not use C++ strategies unless you have all of the server
>source also. Double yuck. Who wants to re-write X, Motif,
>Xview, Sunview, etc? Triple yuck

Perhaps only a single yuck.  A yuck and a half?

There is a hack to get C++ member functions called from a system that uses
C callbacks, as long as there is a way to hang a pointer off of the
"server" object.  For example, in say you wanted to define a SunView class,
TkFrame, that could handle events:

    class TkFrame {
    public:
	TkFrame() { handle = 0; }
	Frame Create();
	void EventHandler(Event*, void*);
    private:
	Frame handle;
    };

The trick is to associate a pointer to an instance of TkFrame with the
SunView Frame, and to define an ordinary, non-member function as the
callback:

    Frame TkFrame::Create()
    {
	handle = window_create(NULL, FRAME,
		WIN_CLIENT_DATA, this,
		WIN_EVENT_PROC, ::EventHandler,
		0);
	return handle;
    }

The ordinary function just yanks the pointer to a TkFrame out of the
Frame and calls the member function:

    static void EventHandler(Frame handle, Event* event, void* arg)
    {
	TkFrame* frame = (TkFrame*) window_get(handle, WIN_CLIENT_DATA);
	frame->EventHandler(event, arg);
    }

Not pretty, but it gets the job done.

Jim Muth
Online Computer Systems, Inc
jim@ocsmd.ocs.com

robert@ireq.hydro.qc.ca (R.Meunier 8516) (10/02/90)

	I'm trying to implement a stack objet with ptr to function
as members. But i can't go through the compiler (SUN C++)

Here is a part of the code, can someone point me out what is
wrong.


--------------------------------------------------------------------


#include <stream.h>


class ST
{
	void *data;
	void (*ptrFct)(void *);
public:
	ST(void *, void (*)(void *));
	void exec();
};

ST::ST(void *d, void (*ptr)(void *))
{
	data = d;
	ptrFct = ptr;
}

void ST::exec()
{
	(*ptrFct)(data);
}

void foo1(int *a)
{
	*a += 1;
}

void foo2(float *a)
{
	*a += 1;
}

main()
{
int aa=10;
float bb=100;

void foo1(int *);
void foo2(float *);

ST a(&aa,foo1);
ST b(&bb,foo2);

	a.exec();	
	a.exec();
}


--------------------------------------------------------------------

	I get those error message from the compiler:
"p1.cc", line 44: error:
	bad argument  2 type for ST::ST(): void (*)(int *) ( void (*)(void *) expected)
"p1.cc", line 45: error:
	bad argument  2 type for ST::ST(): void (*)(float *) ( void (*)(void *) expected)


	so i have not define the parameter by putting (...) like that

--------------------------------------------------------------------
#include <stream.h>


class ST
{
	void *data;
	void (*ptrFct)(...);
public:
	ST(void *, void (*)(...));
	void exec();
};

ST::ST(void *d, void (*ptr)(...))
{
	data = d;
	ptrFct = ptr;
}

void ST::exec()
{
	(*ptrFct)(data);
}

void foo1(int *a)
{
	*a += 1;
}

void foo2(float *a)
{
	*a += 1;
}

main()
{
int aa=10;
float bb=100;

void foo1(...);
void foo2(...);

ST a(&aa,foo1);
ST b(&bb,foo2);

	a.exec();	
	a.exec();
}



--------------------------------------------------------------------


   With that code, i get ld: Undefined symbol 
                             _foo1()    
                             _foo2()   

	because the compiler is trying to overload foo1 and foo2 since the
parameter do not match.

	What should i do?

P.S. In case you are wondering what i am trying to do, i am implemanting
a small task library that will collect ptr to data and ptr to function
and execute them later. The function are always of the form:

Function(DATA *ptr)
{
}

with function and DATA undefined by the task manager (declare as void *)

--
-----------------------------------------------------------------------
Robert Meunier                     Institut de Recherche d'Hydro-Quebec
Ingenieur                          1800 Montee Ste-Julie, Varennes
Internet: robert@ireq.hydro.qc.ca  Qc, Canada, J3X 1S1 

basti@orthogo.UUCP (Sebastian Wangnick) (10/18/90)

robert@ireq.hydro.qc.ca (R.Meunier 8516) writes:

>	I'm trying to implement a stack objet with ptr to function
>as members. But i can't go through the compiler (SUN C++)

Use the first example.
Use typedef void (*ProcVoid) (void*) and cast to it:

>main()
>{
>int aa=10;
>float bb=100;

>void foo1(int *);
>void foo2(float *);

>ST a(&aa,ProcVoid(foo1));
>ST b(&bb,ProcVoid(foo2));

>	a.exec();	
>	a.exec();
>}

Hope that works,

Sebastian Wangnick (basti@orthogo.uucp)