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