Skip to main content
gamedev.net
🔒 Locked

class member function pointers

Started by Wayfarer 5 replies 200+ views
Original Post
Wayfarer
Wayfarer
Ok. This is driving me nuts. I want to create an array of class member function pointers and then invoke the call in each one. Here's what I got:
        

class Test {

 protected:

 public:
 Test(void);
 ~Test(void);

 typedef void (Test::*function_ptr)();

 function_ptr function_ptrs[16]; 

 void Call_Me1();
 void Call_Me2();
 void Call_Me3();
 // etc..

};


Test::Test(void) {

 function_ptrs[0] = Call_Me1;
 function_ptrs[1] = Call_Me2;
 function_ptrs[2] = Call_Me3;
 // etc..

}

        
The above code seems to compile ok. And I'm trying to invoke the call with: for(i=0; i < 16; i++) { (*function_ptrs [ i ] )(); } But, this line gives me a compilation error: error C2064: term does not evaluate to a function Any thoughts? I'm going to try it again tomorrow. Wayfarer Edited by - Wayfarer on 7/3/00 12:50:28 AM
MK42
MK42
Hi!

Just a simple bug, you are dereferencing the function you are trying to call. Just try:

for(i=0; i < 16; i++) {
function_ptrs();
}

That should work ... isn''t C cool?

Ciao,

MK42
Wayfarer
Wayfarer
I'm sorry, that didn't work either. I've tried a bunch of different variations,
but I still can't get it to compile. Something in the syntax is wrong. BTW,
I'm using z as a variable instead of i now, since this board treats i in
brackets as italics.

        

Test::Test(void) {

function_ptrs[0] = Call_Me1;
function_ptrs[1] = Call_Me2;
function_ptrs[2] = Call_Me3;
// etc..


for(int z=0; z < 16; z++) {

// does not compile

function_ptrs[z]();
}
}




Wayfarer

Edited by - Wayfarer on July 3, 2000 1:05:36 PM
MK42
MK42
Strangely, in C (without thiscall functions) this works:

void Call_Me1(){
printf("1\n");
}

void Call_Me2(){
printf("2\n");
}

void Call_Me3(){
printf("3\n");
}

typedef void (*function_ptr)();

function_ptr function_ptrs[3];

void main(){
function_ptrs[0]=Call_Me1;
function_ptrs[1]=Call_Me2;
function_ptrs[2]=Call_Me3;

function_ptrs[0]();
function_ptrs[1]();
function_ptrs[2]();
}

Sorry for the formatting ... how do you do the highlighted code?

I guess the problem is that the function you are trying to call is a method in a class. The compiler needs the ''this'' pointer, but doesn''t get it. I think, only a bit of asm can do the trick (only works with VC++, though). (Warning: Hacking ahead!!)

void *func_ptr;

void getFuncPtr(char* funcName, ...){
va_list va;
va_start(va, funcName);
func_ptr = va_arg(va, void*); //''Cast'' function pointer
va_end(va);
// Add funcName & func to a map/dictionary
}

for(int z = 0;z<16;z++){
getFuncPtr("Blah",function_ptrs[z]);

__asm
{
mov ecx, this
call func_ptr
add esp, 0 //4 * numargs
}
}

This works, but is pretty hacked. You could even pass Test::Call_Me1 as the second argument to getFuncPtr(). It basically is used to ''cast'' the thiscall to a generic void*. The little ASM snippet moves the ''this''-pointer to ECX and calls the function retrieved by getFuncPtr(). If you want me to explain a bit more go ahead (unless this is too hacked for ya).

Ciao,

MK42

PS: I really need to know the commands for this board. BTW, how do you do tabs (or just spaces)?
Wayfarer
Wayfarer
I think you're right, function pointers are treated differently in C and
C++. After much searching, I found the solution!

    

Test::Test(void) {

function_ptrs[0] = Call_Me1;
function_ptrs[1] = Call_Me2;
function_ptrs[2] = Call_Me3;
// etc..


for(int z=0; z < 16; z++) {
(this->*function_ptrs[z])();
}
}



You can access the hidden 'this' pointer in any class member function,
so I don't have to explicity pass it as a parameter.

To do source code inserts like the one above, simply place your text
between the keywords [ source ] and [ / source ]. But don't use spaces
like I just did. And I don't think you can properly format text
using spaces. The board just strips them out.


Wayfarer


Edited by - Wayfarer on July 3, 2000 5:24:46 PM
MK42
MK42
Actually I didn''t pass the ''this'' pointer as a parameter. The thiscall calling convention states, that the ''this'' pointer is stored in ECX. Parameters are pushed on the stack in reverse order (right to left). Then you do the call on the pointer to the function. Basically, I did what the compiler does to your code. Nonetheless, your code is cooler, since it''s compiler independent (and I''ve been looking for a cleaner way to do this).

Hey, this thread was pretty educational,

MK42

PS: Thanks for the tags!!
MikeD
MikeD
Yeah, in essence the compiler didn''t know that that the function calls you were making were associated with the object so you had to explicitly tell it which object you were calling it in reference to. The same as if you''d called it in a non-member function.

Mike

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.