[comp.lang.c++] Passing virtual functions around.

gjditchfield@watmsg.waterloo.edu (Glen Ditchfield) (04/18/88)

More news from the frontiers of compiler abuse...
   I want to call an unusual C function from C++.  Calls look like
	result = emit(fptr, size, p1, ... pn)
where fptr is a pointer to a function that may return an integer or void,
and size is an integer.  emit() calls fptr and passes it p1, .. pn as
arguments.  (emit() is part of a light-weight task library.)
   I want to pass a virtual function through fptr.  How do I phrase the
call?  So far, I have found four ways that don't work.  One of these causes
an internal cfront error, and one causes the C compiler to produce errors.
----------------------------------------
typedef int procid;
extern procid emit(...);
extern int absorb(procid);
extern int cprintf(char*, ...);	// ...for serialized printing.

class task {
    procid pid;
  public:
    virtual void body();
    task(int stacksize);
    ~task();
    };

task::~task() {
    absorb(pid);
    };

task::task(int stacksize) {
    pid = emit( &body, stacksize, this);
//"err2.cc", line 23: warning: address of bound function (try task ::* pointer type and &task ::body  address)
    };

void task::body() {
    cprintf("Error: no task body specified.\n");
    };

class test:public task {
  public:
    test():(2000){};
    void body();
    };

void test::body() {
    cprintf("Test body executed.\n");
    };

main() {
    test t;
    };
This version prints "Error: no task body specified."
It's calling the wrong body().
----------------------------------------
If I heed the warning message and change task::task() to
	task::task(int stacksize) {
    	    pid = emit( &task::body, stacksize, this);
    	    };
The c code generated by cfront for the above is
	_au0_this -> _task_pid = emit ( ((char (*)())1), _au0_stacksize , _au0_this ) ;
which isn't what I intended.  Is this really the way pointers to virtual
functions are implemented?
----------------------------------------
A bug: change it to
	task::task(int stacksize) {
	    pid = emit( body, stacksize, this);
	    };
and I get
cc    err3..c /usr/lib/libccc.a
"err3.cc", line 27: "_task_body" undefined
"err3.cc", line 27: member of structure or union required
"err3.cc", line 27: value of void expression used
----------------------------------------
A bug: change it to
	task::task(int stacksize) {
	    typedef void (task::*PVVMF)();
	    PVVMF pmf = &task::body;
	    pid = emit( this->*pmf, stacksize, this);
	    };
"err1.cc", line 26: internal <<cfront 1.2.1 2/16/87>> error:  299920-> expression::print .*
----------------------------------------
Glen Ditchfield                      {watmath,utzoo,ihnp4}!watrose!gjditchfield
Dept of Computer Science, U of Waterloo         (519) 885-1211 x6658
Waterloo, Ontario, Canada			   Office: MC 2006
If you grab the bull by the horns, you at least confuse him -- R.A.Heinlein
--
Glen Ditchfield                      {watmath,utzoo,ihnp4}!watrose!gjditchfield
Dept of Computer Science, U of Waterloo         (519) 885-1211 x6658
Waterloo, Ontario, Canada			   Office: MC 2006
If you grab the bull by the horns, you at least confuse him -- R.A.Heinlein