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!
Related
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])();
}
I'm having a small problem which I can't wrap my head around.
I have a function that looks like this:
template <typename T>
std::unique_ptr<Environment>& CreateEnvironment(sf::Vector2f& _position, bool _addToStatic = false);
This is my function pointer typedef
typedef std::unique_ptr<Environment>& (WorldEditor::*CreateEnvironmentPtr)(sf::Vector2f&, bool);
std::map<std::string,CreateEnvironmentPtr> listEnv;
And I'm trying to simply do this:
listEnv["test"] = &CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
And i get the following error:
error C2440: '=' : cannot convert from 'std::unique_ptr<_Ty> *' to
'std::unique_ptr<_Ty> &(__thiscall WorldEditor::* )(sf::Vector2f
&,bool)'
I understand what the error is saying, but I don't know how to solve it. Also why does it even care about the return type when I'm pointing to the address of the function?
Best regards
nilo
problems such as these are often much better solved with std::function
std::map<std::string, std::function<void()> listEnv;
listEnv.emplace("test", [] {
CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
});
to call:
listEnv.at("test")->second();
Based on your post I am not sure if you are attempting to create the member function pointer and map inside the CreateEnvironment class or outside of it, so I'll solve what I think is the more difficult problem of pointer to a separate object's member function.
I simplified your classes like so:
Environment
struct Environment
{
int i = 1;
};
Coin
struct Coin
{
int k = 0;
};
WorldEditor
struct WorldEditor
{
template <typename T>
std::unique_ptr<Environment> CreateEnvironment(int& _j, bool _addToStatic = false)
{
return std::make_unique<Environment>();
}
};
Solution: Map an object's member fn pointer, and then call it later
(I will be using C++11/14 syntax in my answer)
//declare a pointer to member function in WorldEditor
using CreateEnvironmentPtr = std::unique_ptr<Environment> (WorldEditor::*)(int&, bool);
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to the CreateEnvironment<Coin> function
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = &WorldEditor::CreateEnvironment<Coin>;
// call the member function pointer using the instance I created, as well as
// the mapped function
(myWorldEditor.*listEnv["test"])(myInt, false);
// (printing member value to cout to show it worked)
std::cout << (myWorldEditor.*listEnv["test"])(myInt, false)->i << std::endl; // prints 1
Live Demo
Solution 2: use std::bind and std::function
Perhaps we already know the parameters to the member function call at the time we create the entry for map. Using std::bind with a std::function will help us achieve that (Similar to Richard Hodges' solution):
// now our "function pointer" is really just a std::function that takes no arguments
using CreateEnvironmentPtr = std::function<std::unique_ptr<Environment>(void)>;
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to that function pointer
//ensure it gets called with the right args
// by using std::bind (which will also make the arg list appear the be void at call time)
// note that std::bind needs an instance of the class immediately after
// listing the function it should be binding
// only afterwards will we then pass the int& and bool
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = std::bind(&WorldEditor::CreateEnvironment<Coin>, &myWorldEditor, myInt, false);
// the mapped function
listEnv["test"]()->i;
// (printing resulting unique_ptr<Environment>'s member to cout to show it worked)
std::cout << listEnv["test"]()->i << std::endl; // prints 1
Live Demo 2
So I am unsure why this wont work, ive tried some googling, i just cant find out what the problem is
void Player::Cmd(std::vector<std::string> &tokens)
{
std::string str = tokens[0];
std::map<std::string, void (Player::*)()>::iterator it = playerCommands.find(str);
Func fun;
if (it != playerCommands.end())
{
fun = it->second; //i tried it->second(); same issue
fun(); //error C2064: term does not evaluate to a
//function taking 0 arguments
}
else
{
std::cout << "What? \n";
}
}
git hub for the project
https://github.com/lordkuragari/TextRPG
Contrary to your belief, your map doesn't hold function pointers. So you cannot call the elements in the map.
Rather, your map contains pointers to member functions. Non-static member functions aren't functions and cannot be called; rather, they have to be invoked on an object. You can invoke a member function on an object given by a pointer p via a function pointer ptfm like this:
(p->*ptmf)();
In your case, presumably you want to use p = this and ptfm = fun, so it'd be:
(this->*fun)();
Or, without the local variable:
(this->*it->second)();
In C++17 you can also use std::invoke(it->second, this).
Is there a way, I can switch between 2 similar function sets (C/C++) in an effective way?
To explain better what I mean, lets say I have 2 sets of global functions like:
void a_someCoolFunction();
void a_anotherCoolFunction(int withParameters);
…
void b_someCoolFunction();
void b_anotherCoolFunction(int withParameters);
…
And I want to able to "switch" in my program at runtime which one is used. BUT: I dont want to have one if condition at every function, like:
void inline someCoolFunction(){
if(someState = A_STATE){
a_someCoolFunction();
}else{
b_someCoolFunction();
}
}
Because, I expect that every function is called a lot in my mainloop - so It would be preferable if I could do something like this (at start of my mainloop or when someState is changed):
if(someState = A_STATE){
useFunctionsOfType = a;
}else{
useFunctionsOfType = b;
}
and then simply call
useFunctionsOfType _someCoolFunction();
I hope its understandable what I mean… My Background: Im writing an App, that should be able to handle OpenGL ES 1.1 and OpenGL ES 2.0 both properly - but I dont want to write every render Method 2 times (like: renderOpenGL1() and renderOpenGL2() I would rather to write only render()). I already have similiar Methods like: glLoadIdentity(); myLoadIdentity(); … But need a way to switch between these two somehow.
Is there any way to accomplish this in an efficent way?
Several options, including (but not limited to):
Use function pointers.
Wrap them in classes, and use polymorphism.
Have two separate copies of the loop.
But please profile to ensure this is actually a problem, before you make any large changes to your code.
As the question seems to be interested in a C++ solution and no-one has spelt out the polymorphic solution (too obvious?), here goes.
Define an abstract base class with the API you require, and then implement a derived class for each supported implementation:
class OpenGLAbstract
{
public:
virtual ~OpenGLAbstract() {}
virtual void loadIdentity() = 0;
virtual void someFunction() = 0;
};
class OpenGLEs11 : public OpenGLAbstract
{
public:
virtual void loadIdentity()
{
// Call 1.1 API
}
virtual void someFunction()
{
// Call 1.1 API
}
};
class OpenGLEs20 : public OpenGLAbstract
{
public:
virtual void loadIdentity()
{
// Call 2.0 API
}
virtual void someFunction()
{
// Call 2.0 API
}
};
int main()
{
// Select the API to use:
bool want11 = true;
OpenGLAbstract* gl = 0;
if (want11)
gl = new OpenGLEs11;
else
gl = new OpenGLEs20;
// In the main loop.
gl->loadIdentity();
delete gl;
}
Note that this is exactly the sort of thing that C++ was intended for, so if can use C++ here, this is the simplest way to go.
Now a more subtle issue you might face is if your 2.0 version requires the process to load a dynamic linked library at run time with the 2.0 platform implementation. In that case just supporting the API switch is not enough (whatever the solution). Instead put each OpenGL concrete class in its own linked library and in each provide a factory function to create that class:
OpenGlAbstract* create();
Then load the desired library at run time and call the create() method to access the API.
In C (since it seems you want both C and C++) this is done with pointer to functions.
// Globals. Default to the a_ functions
void(*theCoolFunction)() = a_someCoolFunction;
void(*theOtherCoolFunction)(int) = a_anotherCoolFunction;
// In the code ...
{
...
// use the other functions
theCoolFunction = b_someCoolFunction;
theOtherCoolFunction = b_anotherCoolFunction;
...
}
You might probably want to switch those functions in groups, so you better set a array of pointers to functions and pass that array around. If you decide to do so, you might probably want to also define some macro to ease the reading:
void (*functions_a[2])();
void (*functions_b[2])();
void (**functions)() = functions_a;
....
#define theCoolFunction() functions[0]()
#define theOtherCoolFunction(x) functions[1](x)
....
// switch grooup:
functions = functions_b;
but in this case you'll lose the static check on argument types (and you have to initialize the array, of course).
I guess in C++ you will have instatiate two different objects with the same parent class and different implementation for their methods (but I'm no C++ prograammer!)
You could use functions pointers. You can read a lot about them if you google it, but briefly a function pointer stores a pointer to a function's memory address.
Function pointers can be used the same way as a funcion, but can be assigned the address of different functions, making it a somehow "dynamic" function. As an example:
typedef int (*func_t)(int);
int divide(int x) {
return x / 2;
}
int multiply(int x) {
return x * 2;
}
int main() {
func_t f = ÷
f(2); //returns 1
f = &multiply;
f(2); //returns 4
}
Something like boost::function (std::function) would fit the bill. Using your example:
#include <iostream>
#include <boost/function.hpp> //requires boost installation
#include <functional> //c++0x header
void a_coolFunction() {
std::cout << "Calling a_coolFunction()" << std::endl;
}
void a_coolFunction(int param) {
std::cout << "Calling a_coolFunction(" << param << ")" << std::endl;
}
void b_coolFunction() {
std::cout << "Calling b_coolFunction()" << std::endl;
}
void b_coolFunction(int param) {
std::cout << "Calling b_coolFunction(" << param << ")" << std::endl;
}
float mul_ints(int x, int y) {return ((float)x)*y;}
int main() {
std::function<void()> f1; //included in c++0x
boost::function<void(int)> f2; //boost, works with current c++
boost::function<float(int,int)> f3;
//casts are necessary to resolve overloaded functions
//otherwise you don't need them
f1 = static_cast<void(*)()>(a_coolFunction);
f2 = static_cast<void(*)(int)>(a_coolFunction);
f1();
f2(5);
//switching
f1 = static_cast<void(*)()>(b_coolFunction);
f2 = static_cast<void(*)(int)>(b_coolFunction);
f1();
f2(7);
//example from boost::function documentation. No cast required.
f3 = mul_ints;
std::cout << f3(5,3) << std::endl;
}
Compiled with g++-4.4.4, this outputs:
Calling a_coolFunction()
Calling a_coolFunction(5)
Calling b_coolFunction()
Calling b_coolFunction(7)
15
The biggest limitation is that the types of f1,f2, etc cannot change, so any function you assign to them must have the same signature (i.e. void(int) in the case of f2).
The simple way could be storing pointers to functions, and change them od demand.
But the better way is to use something similar to abstract factory design pattern. The nice generic implementation can be found in Loki library.
In C you would typically do this with a struct containing function pointers:
struct functiontable {
void (*someCoolFunction)(void);
void (*anotherCoolFunction)(int);
};
const struct functiontable table_a = { &a_someCoolFunction, &a_anotherCoolFunction };
const struct functiontable table_b = { &b_someCoolFunction, &b_anotherCoolFunction };
const struct functiontable *ftable = NULL;
To switch the active function table, you'd use:
ftable = &table_a;
To call the functions, you'd use:
ftable->someCoolFunction();
Think of your basic GLUT programs. They simply run from a main method and contain callbacks like `glutMouseFunc(MouseButton) where MouseButton is the name of a method.
What I have done is I have encapsulated the main file into a class, so that MouseButton is no longer a static function but has an instance. But doing this gives me a compilation error :
Error 2 error C3867: 'StartHand::MouseButton': function call missing argument list; use '&StartHand::MouseButton' to create a pointer to member c:\users\angeleyes\documents\visual studio 2008\projects\capstone ver 4\starthand.cpp 388 IK Engine
It is not possible to provide a code sample as the class is quite huge.
I have tried using this->MouseButton but that gives the same error. Can't a pointer to an instance function be given for callback?
As the error message says, you must use &StartHand::MouseButton syntax to get a pointer to a member function (ptmf); this is simply mandated as part of the language.
When using a ptmf, the function you are calling, glutMouseFunc in this case, must also expect to get a ptmf as a callback, otherwise using your non-static MouseButton won't work. Instead, a common technique is for callbacks to work with a user-supplied void* context, which can be the instance pointer—but the library doing the callbacks must explicitly allow this parameter. It's also important to make sure you match the ABI expected by the external library (the handle_mouse function below).
Since glut doesn't allow user-supplied context, you have to use another mechanism: associate your objects with glut's current window. It does provide a way to get the "current window", however, and I've used this to associate a void* with the window. Then you simply need to create a trampoline to do the type conversion and call the method.
Machinery:
#include <map>
int glutGetWindow() { return 0; } // make this example compile and run ##E##
typedef std::pair<void*, void (*)(void*,int,int,int,int)> MouseCallback;
typedef std::map<int, MouseCallback> MouseCallbacks;
MouseCallbacks mouse_callbacks;
extern "C" void handle_mouse(int button, int state, int x, int y) {
MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow());
if (i != mouse_callbacks.end()) { // should always be true, but possibly not
// if deregistering and events arrive
i->second.second(i->second.first, button, state, x, y);
}
}
void set_mousefunc(
MouseCallback::first_type obj,
MouseCallback::second_type f
) {
assert(obj); // preconditions
assert(f);
mouse_callbacks[glutGetWindow()] = MouseCallback(obj, f);
//glutMouseFunc(handle_mouse); // uncomment in non-example ##E##
handle_mouse(0, 0, 0, 0); // pretend it's triggered immediately ##E##
}
void unset_mousefunc() {
MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow());
if (i != mouse_callbacks.end()) {
mouse_callbacks.erase(i);
//glutMouseFunc(0); // uncomment in non-example ##E##
}
}
Example:
#include <iostream>
struct Example {
void MouseButton(int button, int state, int x, int y) {
std::cout << "callback\n";
}
static void MouseButtonCallback(
void* self, int button, int state, int x, int y
) {
static_cast<Example*>(self)->MouseButton(button, state, x, y);
}
};
int main() {
Example obj;
set_mousefunc(&obj, &Example::MouseButtonCallback);
return 0;
}
Notice that you don't call glutMouseFunc directly anymore; it is managed as part of [un]set_mousefunc.
Just in case it isn't clear: I've rewritten this answer so it should work for you and so that it avoids the C/C++ linkage issue being debated. It will compile and run as-is (without glut), and it should work with glut with only minor modification: comment or uncomment the 4 lines marked ##E##.
No, a pointer to an instance function can not be given to a callback function expecting a function pointer of a certain signature. Their signatures are different. It won't compile.
Generally such APIs allow you to pass in a void* as a "context" parameter. You pass in your object there, and write a wrapper function which takes the context as the callback. The wrapper casts it back to whatever class you were using, and calls the appropriate member function.
You can't replace a static callback with an instance one. When the caller calls your callback, on what instance whoul it call? In other words, how does the caller pass in the formal 'this' argument?
The solution is to have a static callback stub and pass the instance as argument, which implies the callee must accept an arbitrary pvoid that will pass back when invoking the callback. In the stub, you can then call the non-static method:
class C {
void f() {...}
static void F(void* p) {
C* pC = (C*)p;
pC->f();
}
}
C* pC = ...;
someComponent.setCallback(&C::F, pC);
Contrary to what everyone seems to be saying, you most definitely CAN use a non-static member function as a callback method. It requires special syntax designed specifically for getting pointers to non-static members, and special syntax to call that function on a specific instance of a class. See here for a discussion of the needed syntax.
Here is sample code that illustrates how this works:
#include <cstdlib>
#include <string>
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;
class Operational
{
public:
Operational(int value) : value_(value) {};
string FormatValue() const ;
private:
int value_;
};
string Operational::FormatValue() const
{
stringstream ss;
ss << "My value is " << value_;
return ss.str();
}
typedef string(Operational::*FormatFn)() const; // note the funky syntax
Operational make_oper(int val)
{
return Operational(val);
}
int main()
{
// build the list of objects with the instance callbacks we want to call
Operational ops[] = {1, 2, 3, 5, 8, 13};
size_t numOps = sizeof(ops)/sizeof(ops[0]);
// now call the instance callbacks
for( size_t i = 0; i < numOps; ++i )
{
// get the function pointer
FormatFn fn = &Operational::FormatValue;
// get a pointer to the instance
Operational* op = &ops[i];
// call the callback on the instance
string retval = (op->*fn)();
// display the output
cout << "The object # " << hex << (void*)op << " said: '" << retval << "'" << endl;
}
return 0;
}
The output of this program when I ran it on my machine was:
The object # 0017F938 said: 'My value is 1'
The object # 0017F93C said: 'My value is 2'
The object # 0017F940 said: 'My value is 3'
The object # 0017F944 said: 'My value is 5'
The object # 0017F948 said: 'My value is 8'
The object # 0017F94C said: 'My value is 13'
You cannot use a non-static member function in this case.
Basically the type of the argument expected by glutMouseFunc is
void (*)(int, int, int, int)
while the type of your non-static member function is
void (StartHand::*)(int, int, int, int)
First problem is that types don't really match.
Second, in order to be able to call that method, the callback would have to know which object ( i.e. "this" pointer ) your method belongs to ( that's pretty much why the types are different in the first place ).
And third, I think you're using the wrong syntax to retrieve the method's pointer. The right syntax should be: &StartHand::MouseButton.
So, you have to either make that method static or use some other static method that would know which StartHand pointer to use to call MouseButton.
The following works in c++ to define a c callback function, useful for example when using glut (glutDisplayFunc, glutKeyboardFunc, glutMouseFunc ...) when you only need a single instance of this class :
MyClass * ptr_global_instance = NULL;
extern "C" void mouse_buttons_callback(int button, int state, int x, int y) {
// c function call which calls your c++ class method
ptr_global_instance->mouse_buttons_cb(button, state, x, y);
}
void MyClass::mouse_buttons_cb(int button, int state, int x, int y) {
// this is actual body of callback - ie. if (button == GLUT_LEFT_BUTTON) ...
// implemented as a c++ method
}
void MyClass::setup_glut(int argc, char** argv) { // largely boilerplate glut setup
glutInit(&argc, argv);
// ... the usual suspects go here like glutInitWindowSize(900, 800); ...
setupMouseButtonCallback(); // <-- custom linkage of c++ to cb
// ... other glut setup calls here
}
void MyClass::setupMouseButtonCallback() {
// c++ method which registers c function callback
::ptr_global_instance = this;
::glutMouseFunc(::mouse_buttons_callback);
}
In your MyClass header we add :
void mouse_buttons_cb(int button, int state, int x, int y);
void setupMouseButtonCallback();
This also works using identical logic flows to setup your glut
call to glutDisplayFunc(display)