[comp.lang.c++] indirect message passing

880716a@aucs.uucp (Dave Astels) (05/31/90)

I am wondering if it is possible to pass messages in C++ indirectly.
Let me explain:  say I have a class X which has a member function foo().
Also, I have a variable y of type X.  Rather than invoking y.foo() directly
I want to store the information for later use.  ie. I want to set up a
callback (using X11 terminology).. to store the information that X::foo()
is to be called for the object y, then do the call later (in response to
some event, for example).  I have done this in a UI I developed in Turbo
Pascal 5.5.  I have since bought Zortech C++, and wish to eventually
rewrite the UI in C++.  The technique in TP was implemented using generic
pointers (to the object and the method entry point), and some assembly to
do the actual method invocation (supplying the Self/this parameter, etc).
-- 
- Dave

Internet: 880716a@AcadiaU.CA
Bitnet:   880716a@Acadia

sdm@cs.brown.edu (Scott Meyers) (06/01/90)

In article <1990May31.131937.25923@aucs.uucp> 880716a@aucs.uucp (Dave Astels) writes:
>I am wondering if it is possible to pass messages in C++ indirectly.
>Let me explain:  say I have a class X which has a member function foo().
>Also, I have a variable y of type X.  Rather than invoking y.foo() directly
>I want to store the information for later use.  ie. I want to set up a
>callback (using X11 terminology).. to store the information that X::foo()
>is to be called for the object y, then do the call later (in response to
>some event, for example).  I have done this in a UI I developed in Turbo
>Pascal 5.5.  I have since bought Zortech C++, and wish to eventually
>rewrite the UI in C++.  The technique in TP was implemented using generic
>pointers (to the object and the method entry point), and some assembly to
>do the actual method invocation (supplying the Self/this parameter, etc).

Try this -- it works fine under cfront 2.0 (no assembly required):

    #include <iostream.h>

    class X {
    public:
      void foo() { cout << "Foo!\n"; }
    };

    main()
    {
      cout << "Declaring an X called y...\n";
      X y;

      cout << "Calling y.foo() directly...";
      y.foo();

      cout << "Declaring pointers...\n";
      X *py;
      py = &y;
      void (X::*pxmf)();
      pxmf = X::foo;

      cout << "Calling y.foo() indirectly...";
      (py->*pxmf)();
    }  

For details, see Lippman, p. 213ff.

Scott
sdm@cs.brown.edu

880716a@aucs.uucp (Dave Astels) (06/01/90)

In article <41462@brunix.UUCP> sdm@cs.brown.edu (Scott Meyers) writes:
>In article <1990May31.131937.25923@aucs.uucp> 880716a@aucs.uucp (Dave Astels) writes:
>>I am wondering if it is possible to pass messages in C++ indirectly.
>
>      cout << "Declaring pointers...\n";
>      X *py;
>      py = &y;
>      void (X::*pxmf)();
>      pxmf = X::foo;
>
>      cout << "Calling y.foo() indirectly...";
>      (py->*pxmf)();
>    }  
>

Yes, but I want to be able to have a class to hold the indirect call, as in:

class CallBack {
	void * instance;	// address of instance to be passed the message 
    void * method;		// entry point of the method
public:
	CallBack (void *, void *);
	Send (void);
}

Then I want to be able to set up an indirect call via something like:

	CallBack cb (&y, (X::*foo)());   // is the -> member syntax correct ?

and later perform the call by

	cb.Send ();

I realize that this probably can't work with virtual methods (on first
consideration), but I don't think that is a problem in my case (the TP
version won't either, and it works fine for what I need).

The use of this:  Consider a menu (for example).  There is a CallBack
connected to each option.  When an option is selected its CallBack gets
passed a `Send' message, thus invoking the proper action .. sending a message
to some other object.  This technique enables the construction of a very
sofisticated, event-driven UI with little (if any) programming overhead to
make it run, once the initial set up of all the components is performed.

-- 
- Dave Astels

Internet: 880716a@AcadiaU.CA
Bitnet:   880716a@Acadia

roman@sparc7.hri.com (Roman) (06/02/90)

In article <1990Jun1.114837.11151@aucs.uucp>, 880716a@aucs.uucp (Dave
Astels) writes:
> [deleted]
> 
> Yes, but I want to be able to have a class to hold the indirect call, as in:
> 
> class CallBack {
> 	void * instance;	// address of instance to be passed the message 
>     void * method;		// entry point of the method
> public:
> 	CallBack (void *, void *);
> 	Send (void);
> }
> 
> Then I want to be able to set up an indirect call via something like:
> 
> 	CallBack cb (&y, (X::*foo)());   // is the -> member syntax correct ?
> 
> and later perform the call by
> 
> 	cb.Send ();
> 
> I realize that this probably can't work with virtual methods (on first
> consideration), but I don't think that is a problem in my case (the TP
> version won't either, and it works fine for what I need).
> 
>  [deleted]

> - Dave Astels
> 
> Internet: 880716a@AcadiaU.CA
> Bitnet:   880716a@Acadia


The problem is not with virtuals, but with casting a method pointer to
void*. After the
cast the pointer is useless (you loose information necessary to call the
method).

What about this:

class CallBack {
 public:
  virtual void Send();
};
class CallBackX : public CallBack {
	X* objPtr;
	void (X::*fPtr)();
 public:
		CallBackX(X*,void (X::*)());
		void Send() { (objPtr->*fPtr)(); }
};

Unfortunatly for each X you have to define new CallBack class.