I'm trying to make a table of function pointers within a class. I haven't been able to find any examples of this online, most involve using member function pointers outside of their class.
for example:
class Test
{
typedef void (Test::*FunctionType)();
FunctionType table[0x100];
void TestFunc()
{
}
void FillTable()
{
for(int i = 0; i < 0x100; i++)
table[i] = &Test::TestFunc;
}
void Execute(int which)
{
table[which]();
}
}test;
Gives me the error "term does not evaluate to a function taking 0 arguments".
In this line in the Execute function:
table[which]();
You can't call it like that because it's not a normal function. You have to provide it with an object on which to operate, because it's a pointer to a member function, not a pointer to a function (there's a difference):
(this->*table[which])();
That will make the invoking object whichever object is pointed to by the this pointer (the one that's executing Execute).
Also, when posting errors, make sure to include the line on which the error occurs.
Seth has the right answer. Next time, look up the compiler error number on MSDN and you'll see the same: Compiler Error C2064.
You need a context in which to call your function. In your case, the context is this:
void Execute(int which)
{
(this->*table[which])();
}
Related
I'm getting a compile error (MS VS 2008) that I just don't understand. After messing with it for many hours, it's all blurry and I feel like there's something very obvious (and very stupid) that I'm missing. Here's the essential code:
typedef int (C::*PFN)(int);
struct MAP_ENTRY
{
int id;
PFN pfn;
};
class C
{
...
int Dispatch(int, int);
MAP_ENTRY *pMap;
...
};
int C::Dispatch(int id, int val)
{
for (MAP_ENTRY *p = pMap; p->id != 0; ++p)
{
if (p->id == id)
return p->pfn(val); // <--- error here
}
return 0;
}
The compiler claims at the arrow that the "term does not evaluate to a function taking 1 argument". Why not? PFN is prototyped as a function taking one argument, and MAP_ENTRY.pfn is a PFN. What am I missing here?
p->pfn is a pointer of pointer-to-member-function type. In order to call a function through such a pointer you need to use either operator ->* or operator .* and supply an object of type C as the left operand. You didn't.
I don't know which object of type C is supposed to be used here - only you know that - but in your example it could be *this. In that case the call might look as follows
(this->*p->pfn)(val)
In order to make it look a bit less convoluted, you can introduce an intermediate variable
PFN pfn = p->pfn;
(this->*pfn)(val);
Try
return (this->*p->pfn)(val);
Just to chime in with my own experience, I've come across an error in g++ caused by this statement:
(this -> *stateHandler)() ;
Where stateHandler is a pointer to a void member function of the class referenced by *this. The problem was caused by the spaces between the arrow operator. The following snippet compiles fine:
(this->*stateHandler)() ;
I'm using g++ (GCC) 4.4.2 20090825 (prerelease). FWIW.
p->pfn is a function pointer. You need to use * to make it function. Change to
(*(p->pfn))(val)
Have a structure:
scheduled_call {
MyClass* object;
int value;
void (MyClass::*setter)(const int)
}
For class:
MyClass {
void doSomething(const int);
}
The structure compiles all well, but when I try to call the value as function, it throws error:
I need to execute call saved in this structure. I tried this:
void executeIt(scheduled_call cl) {
cl.object->*(cl.method)(cl.value);
}
But I get:
error C2064: term does not evaluate to a function taking 1 arguments
My coding is based on C/C++ function pointer guide. I'm doing this as an experiment, if it fails I can fallback to switch statement of course.
Can anybody compile this under Visual Studio 2010?
You need to provide a valid member function pointer definition in your struct:
scheduled_call {
MyClass* object;
int value;
void (MyClass::*method)(int); // <<<<
}
void MyClass::*method;
Is not a valid function pointer to a class memeber function. To get that we need
void (MyClass::*method)(int)
An now method is a pointer to function like MyClass::doSomething()
The problem was in method call. This is wrong:
cl.object->*(cl.method)(cl.value);
This is correct:
(cl.object->*cl.method)(cl.value);
I am creating a wrapper class that wraps a bunch of functions outlined in a particular 3rd party API. When I try to wrap non-member functions like this:
(AVTcamDllWrapper.h)
typedef VmbErrorType (WINAPI * AVTGETCAMERAS) (CameraPtrVector cameras);
class CAVTcamDllWrapper
{
HMODULE mAVTCamLibrary; //I later have this point to the DLL
public:
void AVTGetCameras (CameraPtrVector cameras);
};
(AVTcamDllWrapper.cpp)
void CAVTcamDllWrapper::AVTGetCameras(AVTNS CameraPtrVector cameras)
{
AVTGETCAMERAS pFunc = NULL;
pFunc = (AVTGETCAMERAS) GetProcAddress(mAVTCamLibrary, "?GetCameras#VimbaSystem#VmbAPI#AVT##AEAA?AW4VmbErrorType##PEAV?$shared_ptr#VCamera#VmbAPI#AVT###23#AEAI#Z");
DWORD dw = GetLastError();
if(pFunc == NULL)
{
Exlog(L"CAVTcamDllWrapper::AVTGetCameras: Failed to locate AVTGetCameras method in AVTCamera DLL.");
NIERR_SET_AND_THROW_ERROR(NIERR_CAMERA_ERROR, L"Failed to locate AVTGetCameras method in AVTCamera DLL.");
}
VmbErrorType vErr = pFunc(cameras);
if(vErr != VmbErrorSuccess)
{
wstring exLogMsg = Format(exLogMsg, L"CAVTcamDllWrapper::AVTGetCameras(): Failed to get any cameras. VmbErrorType = %d", vErr);
Exlog(exLogMsg.c_str());
NIERR_SET_AND_THROW_ERROR(NIERR_CAMERA_ERROR, L"Failed to get any cameras.");
}
}
The above code works great for non-member functions. For example, if I am trying to wrap a function that is called simply by saying:
CallFunction(blah, blaaaaah);
then the wrapper class works fine, and the pFunc is set properly and no error occurs on the VmbErrorType vErr = pFunc(); line;
However, many of my functions are member function, and are called like this:
SomeObject.CallMemberFunction(blah, bleh);
// or
SomeObjectPointer->CallMemberFunction(what, ever);
and these are the functions I can't seem to wrap. The error occurs on the line:
VmbErrorType vErr = pFunc();
because the function cannot be called without a specific object to call it from. In my example, I am wrapping a function GetCameras which exists inside of Camera. Without wrapping the function, to call it I simply create a vector of Camera pointers, and do:
cameras[0]->GetCameras(VmbAccessModeFull);
which works. But I have no idea how I would go about wrapping this function, as the call to GetCameras is both dependent on cameras[0] and completely useless without a camera to call it from.
So how do I wrap member functions like the one shown above?
Edit 1:
I have tried to pass in a reference to a specific object and do
VmbErrorType vErr = theObject->pFunc();
but obviously this won't work because then it will think to look for a function named pFunc inside of theObject, which doesn't exist.
Edit 2:
I feel like I would almost have modify the wrapper function to pass the reference object in as a parameter or something. So like instead of the regular:
cameras[0]->GetCameras(VmbAccessModeFull);
I would have to modify some stuff and make my wrapper function look like this:
mWrapperObject->WrappedGetCameras(VmbAccessModeFull, cameras[0]);
so that the wrapped function will have the context it needs to act as a member function.
To call a member function you must have an object at hand. To have an object you must get it from somewhere. The only place a good little well-behaving function can get stuff from is its parameter list.
So each of your functions obviously must have a parameter that receives The Object.
If you want your wrapper functions to be callable from C, you cannot have class types as function parameters. So you either declare it as a void* and do a cast inside, or just cheat and type it (for C only!) struct YourClassName* (without ever defining the struct). For C++, it should still use the class keyword. Use the preprocessor.
In a nutshell,
foo->bar(moo, roo)
is the fancy shmancy C++ way of saying
FooType_bar(foo, moo, roo)
and you should think about wrapping the latter while actually spelling the former.
How the caller obtains The Object then? One of your functions could create objects (with new) and return pointers to them. Another one could do a delete. Or you can return pointers to elements of a pre-allocated array. Or whatever. Basically you wrap the ways you use to obtain pointers to objects as a user of the original, unwrapped library.
That's about it.
You just need to pass the this pointer as first argument if you are calling memberfunctions and make sure you are using the right calling convention. For static member functions you don´t have to pass the this pointer.
On x64 you would not even have to worry about calling conventions, as everything will be compiled as __fastcall. No matter what calling convention you specify.
#include <iostream>
#include <stdint.h>
class Camera
{
int i;
public:
Camera()
{
i = 123;
}
void __stdcall print_1(int j, int k)
{
std::cout << i << j << k << std::endl;
}
void __cdecl print_2(int j, int k)
{
std::cout << i << j << k << std::endl;
}
void print_3(int j, int k)
{
std::cout << i << j << k << std::endl;
}
static void __cdecl print_s1(int j, int k)
{
std::cout << j << k << std::endl;
}
static void __stdcall print_s2(int j, int k)
{
std::cout << j << k << std::endl;
}
};
int main() {
Camera cam;
Camera* pCam = &cam;
// call __stdcall memberfunction
typedef void (__stdcall* tprint_1)(Camera*,int,int);
tprint_1 print_1 = (tprint_1)&Camera::print_1;
print_1(pCam,1,2);
// call __cdecl memberfunction
typedef void (__cdecl* tprint_2)(Camera*,int,int);
tprint_2 print_2 = (tprint_2)&Camera::print_2;
print_2(pCam,3,4);
// call __thiscall memberfunction
typedef void (__thiscall* tprint_3)(Camera*,int,int);
tprint_3 print_3 = (tprint_3)&Camera::print_3;
print_3(pCam,5,6);
// call __thiscall memberfunction different syntax
typedef void (Camera::* tprint_4)(int,int);
tprint_4 print_4 = (tprint_4)&Camera::print_3;
(pCam->*print_4)(7,8);
// static member functions don´t take a this pointer
typedef void(__cdecl* tprint_s1)(int,int);
tprint_s1 print_s1 = (tprint_s1)&Camera::print_s1;
print_s1(9,10);
// static member functions don´t take a this pointer
typedef void(__stdcall* tprint_s2)(int,int);
tprint_s2 print_s2 = (tprint_s2)&Camera::print_s2;
print_s2(11,12);
return 0;
}
You can do this by converthing the thiscall for memberfunctions to a fastcall
http://www.unknowncheats.me/forum/c-and-c/73849-thiscall-hooking.html
Here's how it's done. Say you have two layers: The member function layer and the wrapper function layer. What you need to do is create a third layer that lies in between these two layers, and export this layer to a .dll file. At first (back when I asked the question) I was trying to wrap functions that looked like this:
void SomeClass::SomeFunction(CString someParam)
{
//blah blah
}
This didn't work because, as the question describes, you cannot wrap member functions. What I discovered was that I needed to do all of the object management on a layer above the member function calls, but still below the wrapper functions. What I ended up with was a bunch of "Bridge" functions (that's what I called them) that "bridge" the gap between the wrapper functions and the member functions. So now, I wrapped functions that looked like this:
void BridgedSomeFunction(CString someParam)
{
classObject.SomeFunction(someParam);
}
Then I simply did some __declspec(dllexport)'s and __declspec(dllimport)'s to turn these functions into a .dll file, and that's it!
I have a problem handling a function pointer.I have made a class Control that has a function pointer as member:
void (*mouseFunction) (Control*, Event*);
The member is protected, and it has setter and getter:
void (*getMouseFunction()) (Control*,Event*)
{
return mouseFunction;
}
void setMouseFunction( void (*mouseFunction) (Control*, Event*) )
{
this->mouseFunction=mouseFunction;
}
The problem is that even after setting the pointer, it's always NULL.
I have a function declared inside a header file:
void mouseFunction (Control* control, Event* event)
{
std::cout << "Inside Text Field";
}
If I try to assign it:
myControlInstance.setMouseFunction(mouseFunction);
If I use the getter to get the pointer it's NULL; and if I try to execute the function I get EXC_BAD_ACCESS:
error: address doesn't contain a section that points to a section in a object file
Following cod is working, so be sure that youre method is public to be accessible from other place than object.
typedef int Event;
class Control
{
public:
void (*mouseFunction) (Control*, Event*);
void (*getMouseFunction()) (Control*,Event*)
{
return mouseFunction;
}
void setMouseFunction( void (*mouseFunction) (Control*, Event*) )
{
this->mouseFunction=mouseFunction;
}
};
void mouseFunction (Control* control, Event* event)
{
printf ("test");
}
int _tmain(int argc, _TCHAR* argv[])
{
Control c;
c.setMouseFunction(mouseFunction);
Event e = 1;
c.mouseFunction(&c,&e);
return 0;
}
Your problem might be with inlining. Since the function is declared and defined at the same point, and inside a header.. the compiler may be treating it as an implicit inline (please note that it is up to the compiler to decide whether or not to actually inline it). If the function is inlined, then the compiler would have to jump through some extra hoops to make it possible to store a pointer to that function (i.e., the compiler would have to have a non-inline version of the function built). If the compiler doesn't make this happen, then you're going to have problems storing and calling a function pointer to the function.
To eliminate this as a possible source of the problem, try moving the function's implementation out into a cpp file, which is one common way to prevent implicit inlining (and usually better style anyway).
I would like to do something like:
for(int i=0;i<10;i++)
addresses[i] = & function(){ callSomeFunction(i) };
Basically, having an array of addresses of functions with behaviours related to a list of numbers.
If it's possible with external classes like Boost.Lambda is ok.
Edit: after some discussion I've come to conclusion that I wasn't explicit enough. Please read Creating function pointers to functions created at runtime
What I really really want to do in the end is:
class X
{
void action();
}
X* objects;
for(int i=0;i<0xFFFF;i++)
addresses[i] = & function(){ objects[i]->action() };
void someFunctionUnknownAtCompileTime()
{
}
void anotherFunctionUnknowAtCompileTime()
{
}
patch someFunctionUnknownAtCompileTime() with assembly to jump to function at addresses[0]
patch anotherFunctionUnknownAtCompileTime() with assembly to jump to function at addresses[1]
sth, I don't think your method will work because of them not being real functions but my bad in not explaining exactly what I want to do.
If I understand you correctly, you're trying to fill a buffer with machine code generated at runtime and get a function pointer to that code so that you can call it.
It is possible, but challenging. You can use reinterpret_cast<> to turn a data pointer into a function pointer, but you'll need to make sure that the memory you allocated for your buffer is flagged as executable by the operating system. That will involve a system call (LocalAlloc() on Windows iirc, can't remember on Unix) rather than a "plain vanilla" malloc/new call.
Assuming you've got an executable block of memory, you'll have to make sure that your machine code respects the calling convention indicated by the function pointer you create. That means pushing/popping the appropriate registers at the beginning of the function, etc.
But, once you've done that, you should be able to use your function pointer just like any other function.
It might be worth looking at an open source JVM (or Mono) to see how they do it. This is the essence of JIT compilation.
Here is an example I just hacked together:
int func1( int op )
{
printf( "func1 %d\n", op );
return 0;
}
int func2( int op )
{
printf( "func2 %d\n", op );
return 0;
}
typedef int (*fp)(int);
int main( int argc, char* argv[] )
{
fp funcs[2] = { func1, func2 };
int i;
for ( i = 0; i < 2; i++ )
{
(*funcs[i])(i);
}
}
The easiest way should be to create a bunch of boost::function objects:
#include <boost/bind.hpp>
#include <boost/function.hpp>
// ...
std::vector< boost::function<void ()> > functors;
for (int i=0; i<10; i++)
functors.push_back(boost::bind(callSomeFunction, i));
// call one of them:
functors[3]();
Note that the elements of the vector are not "real functions" but objects with an overloaded operator(). Usually this shouldn't be a disadvantage and actually be easier to handle than real function pointers.
You can do that simply by defining those functions by some arbitrary names in the global scope beforehand.
This is basically what is said above but modifying your code would look something like this:
std::vector<int (*) (int)> addresses;
for(int i=0;i<10;i++) {
addresses[i] = &myFunction;
}
I'm not horribly clear by what you mean when you say functions created at run time... I don't think you can create a function at run time, but you can assign what function pointers are put into your array/vector at run time. Keep in mind using this method all of your functions need to have the same signature (same return type and parameters).
You can't invoke a member function by itself without the this pointer. All instances of a class have the function stored in one location in memory. When you call p->Function() the value of p is stored somewhere (can't remember if its a register or stack) and that value is used as base offset to calculate locations of the member variables.
So this means you have to store the function pointer and the pointer to the object if you want to invoke a function on it. The general form for this would be something like this:
class MyClass {
void DoStuf();
};
//on the left hand side is a declaration of a member function in the class MyClass taking no parameters and returning void.
//on the right hand side we initialize the function pointer to DoStuff
void (MyClass::*pVoid)() = &MyClass::DoStuff;
MyClass* pMyClass = new MyClass();
//Here we have a pointer to MyClass and we call a function pointed to by pVoid.
pMyClass->pVoid();
As i understand the question, you are trying to create functions at runtime (just as we can do in Ruby). If that is the intention, i'm afraid that it is not possible in compiled languages like C++.
Note: If my understanding of question is not correct, please do not downvote :)