Get the address of a callback function to call dynamically in C++ - c++

I am trying to build an application that can dynamically call any Win32 API function according to user input.
I am wondering how can I have behavior of the function RegisterCallback in C++, because it seems very useful and it can get the address to a callback function.
How can I achieve a same behavior with a function like it in C++?
I already successfully implemented a function which can call any dynamic library, but stuck in such dynamic callbacks.
For example I can call EnumWindows API with my function like below:
CallLibFunction(GetProcAddress(LoadLibrary(L"User32.dll"), "EnumWindows"), ParamArray, 2, ExepInfo);
Thanks in advance.
EDIT: I will explain more.
Assume I have following code:
Callback function:
BOOL CALLBACK EnumWindowsProc(__in HWND hWnd, __in LPARAM lParam)
{
return TRUE;
}
Main Function:
EnumWindows(EnumWindowsProc, NULL);
Above is the usual way anyone can use the API function. I want it to be called like this:
LONGLONG CallbackAddress = <Some Function to get address>&EnumWindowsProc
ParamArray[1].type = VT_I8;
ParamArray[1].llval = CallbackAddress; // Address of `EnumWindowsProc`.
And then finally call it dynamically like:
CallLibFunction(GetProcAddress(LoadLibrary(L"User32.dll"), "EnumWindows"), ParamArray, 2, ExepInfo);

First, you need to declare a pointer type to hold the address of your callback. The basic definition of a function is a bit odd in c++. There is a further complication that in C++ we have functions, function-objects, and template types.
The standard provides a basic function template type:std::function. This type
holds not a function pointer, but a callable object.
#include <functional>
To declare a specific function type, pass its signature to std::function as its template parameter.
typedef std::function<int(const char*)> StdFreeFunc;
// you can also define types for member functions, and define
// member function pointers this way
struct A{};
typedef std::function<int A::*(const char*)> StdMemberFunc;
// member callable objects are called with this syntax:
// (obj.*callable)(args); or (obj->*callable)(args);
// the parenthesis are often required to keep the compiler happy
// A callable object:
struct CallMe
{
int xy;
int operator()(const char*) { /*...*/ return xy; }
};
std::function is compatible with function objects, lambdas and regular function pointers (see below). Works best with C++ only stuff.
struct AStruct
{
StdFreeFunc callback_; // we hold a value, not a pointer
void setCallback(StdFreeFunc&& cb) // pass by value, reference, const ref,
{ // move... like any object type
callback_ = cb;
};
int callCallback(const char* str)
{
if (callback_) // callable object has a bool() operator to check if valid !!
return (callback_)(str);
// the parenthesis and is optional, so this is the same:
if (callback_)
return callback_(str):
}
};
// example with callable object:
AStruct as, ar;
as.setCallback(CallMe{42}); // we can pass an object with data
ar.setCallback(CallMe{84}); // to obtain different effects
as.callCallback("prints fourty two");
ar.callCallback("prints eighty four");
C-style function pointers
Before C++, there was C. THis is how it's done in C, and it does compile. The disadvantage with C-style function pointers is that they are not compatible with function objects. On the other hand they are compatible with C, and many other languages such as PASCAL, VB, etc..
For example, the type a function taking a const char* as a parameter and returning an int is written as:
typedef int (CallBack)(const char*);
The most usual form is to declare a pointer, since that's what is stored. As in:
typedef int (*CallBack)(const char*);
// you can specify extra call specifications
typedef int (__stdcall * CallBack)(const char*); // uses PASCAL calling
// exmample:
struct YourStruct
{
//...
Callback callback_{nullptr}; // this is a pointer initialize to nullptr
//...
void setCallback(Callback cb)
{
// call as ys.setCallback(AFunction)
// or ys.setCallback(&AFunction)
callback_ = cb;
};
int callCallback(const char* str)
{
if (callback_) // always check if valid !!
return (*callback_)(str);
// the parenthesis and the * are optional, so this is the same:
if (callback_)
return callback_(str):
}
};
int UserFunction(const char*) { /*...*/ return 0; }
YourStruct ys;
ys.setCallback(&UserFunction);
ys.callCallback("hello");

Reading your link, the following is said about the callback address:
If the exe running the script is 32-bit, this parameter must be between 0 and 4294967295. If the exe is 64-bit, this parameter can be a 64-bit integer.
So, you need to convert your pointer address to an integer type. Drawing some inspiration from this answer, the following code should give you a hint how to do the conversion in your case:
#include <iostream>
#include <cstdint>
bool f() {
return true;
}
int main() {
int iv = *((int*)(&f));
long lv = *((long*)(&f));
long long llv = *((long long*)(&f));
intptr_t ipv = *((intptr_t*)(&f));
std::cout << "int: " << iv << std::endl;
std::cout << "long: " << lv << std::endl;
std::cout << "long long: " << llv << std::endl;
std::cout << "intptr_t: " << ipv << std::endl;
}
For me this prints:
int: -443987883
long: 82192552476362837
long long: 82192552476362837
intptr_t: 82192552476362837
Note here that an int is to small to cover the void* value. You should be able to convert properly with LONGLONG as well, otherwise intptr_t seems to be the correct data type.

Related

Converting C to CPP with Function Pointers

In my C code, I have the following lines:
void* (*functionSteps[numSteps])();
functionSteps[0] = (void*) filterEvenFoos;
functionSteps[1] = (void*) timesFooByTwo,
functionSteps[2] = (void*) mapFooToBar;
Which works fine. I have an array of functions that return a void* type and take any number of inputs.
I tried to do the same in C++ and I'm getting the error
assigning to 'void *(*)()' from incompatible type 'void *'
Is this not possible in CPP?
Is this not possible in CPP?
functionSteps[0] = (void*) filterEvenFoos;
No, it is not.
It is not really valid C either.
Regarding Function To Pointer Conversion
From https://en.cppreference.com/w/c/language/conversion#Function_to_pointer_conversion:
Any function designator expression, when used in any context other than
as the operand of the address-of operator
as the operand of sizeof
undergoes a conversion to the non-lvalue pointer to the function designated by the expression.
It does not say anything about converting a void* to a function pointer.
Regarding Conversions From void*
You can convert a void* to an object pointer.
From https://en.cppreference.com/w/c/language/conversion#Pointer_conversions:
A pointer to void can be implicitly converted to and from any pointer to object type with the following semantics:
If a pointer to object is converted to a pointer to void and back, its value compares equal to the original pointer.
No other guarantees are offered
Please note even in that section, there is no mention of converting a void* to a function pointer.
It's not clear to me why your computer does not report it as an error.
You can use
functionSteps[0] = filterEvenFoos;
if filterEvenFoos is of the right type of function. If the declaration of filterEvenFoos does not exactly match the expected type, i.e. a function that takes no arguments and returns a void*, then you can't use that either.
Is this not possible in CPP?
Strictly speaking, no, due to type safety and other rules governing function prototypes. However, depending on your needs, that C code can be ported to C++.
Firstly, it should be noted that the function signature of void* fn(); in C is not the same in C++. In C++ to get the same function signature, you need to introduce variadic arguments like so: void* fn(...);, however, it should be noted that you cannot access the variadic arguments portably for a function signature like this.
In C++, void* fn(); is the same as void* fn(void); in C. To this, if your functions had variable inputs in C, you would need to do a little extra work in C++ using the variadic argument list.
For example, if your code were something similar to the following C code:
#include <stdio.h>
#define NUM_STEPS 3
static void* filterEvenFoos(void)
{
printf("42\n");
return NULL;
}
static void* timesFooByTwo(int val)
{
printf("%d\n", (val * 2));
return NULL;
}
static void* mapFooToBar(double obj1, size_t obj2)
{
printf("foo(%f)->bar(%zu)\n", obj1, obj2);
return NULL;
}
int main(void)
{
void* (*functionSteps[NUM_STEPS])();
functionSteps[0] = (void*)filterEvenFoos;
functionSteps[1] = (void*)timesFooByTwo;
functionSteps[2] = (void*)mapFooToBar;
functionSteps[0]();
functionSteps[1](42);
functionSteps[2](3.14, &main);
return 0;
}
You could port it to C++ in many ways, but you could use the va_arg functionality to get variable inputs like so:
#include <iostream>
#include <cstdarg>
#include <vector>
static void* filterEvenFoos(int na, ...)
{
std::cout << 42 << std::endl;
return NULL;
}
static void* timesFooByTwo(int na, ...)
{
va_list vl;
va_start(vl, na);
std::cout << ((va_arg(vl, int)) * 2) << std::endl;
va_end(vl);
return NULL;
}
static void* mapFooToBar(int na, ...)
{
va_list vl;
va_start(vl, na);
double obj1 = va_arg(vl, double);
size_t obj2 = va_arg(vl, size_t);
std::cout << "foo(" << obj1 << ")->bar(" << obj2 << ")" << std::endl;
va_end(vl);
return NULL;
}
int main(int argc, char* argv[])
{
std::vector<void* (*)(int, ...)> functionSteps;
functionSteps.push_back(&filterEvenFoos);
functionSteps.push_back(&timesFooByTwo);
functionSteps.push_back(&mapFooToBar);
functionSteps[0](0);
functionSteps[1](0, 42);
functionSteps[2](0, 3.14, &main);
return 0;
}
You might note that the function signature changes slightly to allow a portable way to access the variadic arguments in each function.
If you're using C++11, you could also make use of the std::function inside the vector, but you still need to have matching function signatures.
You could also make use of classes and inheritance, or template specializations, but those could be extreme over-kill in your scenario.
In the end, it's not a direct port from the C code to C++, but it is doable.
Hope that can help.
It's possible, but the syntax is a bit dicey to get right. It's easier if you use a typedef for your callback-function-type, like this:
#include <stdio.h>
void* filterEvenFoos() {return NULL;}
void* timesFooByTwo() {return NULL;}
void* mapFooToBar() {return NULL;}
typedef void* (*VoidFunction)();
int main(int, char **)
{
const int numSteps = 3;
VoidFunction functionSteps[numSteps];
functionSteps[0] = filterEvenFoos;
functionSteps[1] = timesFooByTwo;
functionSteps[2] = mapFooToBar;
}

ESP was not properly saved across a function call when using function pointers

I am trying to create a program which saves the function pointer of a member function to an array. The program then takes the function pointer from that array and calls the function said pointer points to. This works as long as the member function used does not have any arguments. When I give it arguments the following error occurs in Visual Studio 2017:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
My code is:
typedef uint8_t byte;
template<typename T>
class Test
{
public:
void FuncTest(byte* data)
{
cout << (T)(0.0625f) << endl;
}
};
typedef Test<float> fTest;
typedef Test<long long> lTest;
int main()
{
byte data[1024];
{
void (fTest::*ffp)(byte*) = &fTest::FuncTest;
//void (lTest::*lfp)(byte*) = &lTest::FuncTest;
printf("%p\n", ffp);
memcpy(&data[0], (int64*)&ffp, sizeof(int64));
}
{
int64 pData;
memcpy(&pData, &data[0], sizeof(int64));
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
printf("%p\n", pData);
func_pointer(nullptr);
}
}
If anyone could help, it would be greatly appreciated.
Ignoring the storage in an array your code is essentially:
void (Test::*ffp)(byte*) = &fTest::FuncTest;
void* pData = (void*)ffp;
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
func_pointer(nullptr);
The type of ffp is essentially (although not exactly due to differing calling conventions) void (fTest*, byte*) which doesn't match the type of func_pointer.
The solution to this is to use std::function with with either std::bind or lambdas to convert the function signatures. e.g.:
std::vector<std::function<void(byte*)>> functions;
fTest test;
functions.push_back([=](byte* data){ test.FuncTest(data); });
functions.front()(nullptr);

what's the difference between the function pointer getting from std::function::target<>() and normal function pointer?

The following code is a signal implementation copied from APUE with a little modification
namespace
{
using signal_handler = void (*)(int);
signal_handler signal(sigset_t sig, signal_handler);
}
Signal::signal_handler Signal::signal(sigset_t sig, void (*handler)(int))
{
struct sigaction newAction, oldAction;
sigemptyset(&newAction.sa_mask);
newAction.sa_flags = 0;
newAction.sa_handler = handler;
if (sig == SIGALRM)
{
#ifdef SA_INTERRUPT
newAction.sa_flags |= SA_INTERRUPT;
#endif
}
else
{
newAction.sa_flags |= SA_RESTART;
}
if (sigaction(sig, &newAction, &oldAction) < 0)
throw std::runtime_error("signal error: cannot set a new signal handler.")
return oldAction.sa_handler;
}
The above code works fine during my test, but I wanted to make it more like a C++ code, so I changed signal_handler alias to
using signal_handler = std::function<void (int)>;
and also I use
newAction.sa_handler = handler.target<void (int)>();
to replace
newAction.sa_handler = handler;
and now there is a problem. I find newAction.sa_handler is still NULL after
newAction.sa_handler = handler.target<void (int)>();
but I don't know why. Anyone can help me explain this? thanks.
Here is my test code:
void usr1_handler(int sig)
{
std::cout << "SIGUSR1 happens" << std::endl;
}
void Signal::signal_test()
{
try
{
Signal::signal(SIGUSR1, usr1_handler);
}
catch (std::runtime_error &err)
{
std::cout << err.what();
return;
}
raise(SIGUSR1);
}
Even when using the original code when I run it in Xcode, there is no output. Instead, I run the executable file manually, I can see SIGUSR1 happens in the terminal. Why? How can I see the output using Xcode?
The direct answer is that target() is very picky - you must name the type of the target exactly to get a pointer to it, otherwise you get a null pointer. When you set your signal to usr1_handler, that is a pointer to a function (not a function) - its type is void(*)(int), not void(int). So you're simply giving the wrong type to target(). If you change:
handler.target<void (int)>();
to
handler.target<void(*)(int)>();
that would give you the correct target.
But note what target() actually returns:
template< class T >
T* target();
It returns a pointer to the provided type - in this case that would be a void(**)(int). You'd need to dereference that before doing further assignment. Something like:
void(**p)(int) = handler.target<void(*)(int)>();
if (!p) {
// some error handling
}
newAction.sa_handler = *p;
Demo.
However, the real answer is that this makes little sense to do. std::function<Sig> is a type erased callable for the given Sig - it can be a pointer to a function, a pointer to a member function, or even a wrapped function object of arbitrary size. It is a very generic solution. But sigaction doesn't accept just any kind of generic callable - it accepts specifically a void(*)(int).
By creating a signature of:
std::function<void(int)> signal(sigset_t sig, std::function<void(int)> );
you are creating the illusion that you are allowing any callable! So, I might try to pass something like:
struct X {
void handler(int ) { ... }
};
X x;
signal(SIGUSR1, [&x](int s){ x.handler(s); });
That's allowed by your signature - I'm providing a callable that takes an int. But that callable isn't convertible to a function pointer, so it's not something that you can pass into sigaction(), so this is just erroneous code that can never work - this is a guaranteed runtime failure.
Even worse, I might pass something that is convertible to a function pointer, but may not know that that's what you need, so I give you the wrong thing:
// this will not work, since it's not a function pointer
signal(SIGUSR1, [](int s){ std::cout << s; });
// but this would have, if only I knew I had to do it
signal(SIGUSR1, +[](int s){ std::cout << s; });
Since sigaction() limits you to just function pointers, you should limit your interface to it to just function pointers. Strongly prefer what you had before. Use the type system to catch errors - only use type erasure when it makes sense.
Here you a little example that will help you to understand the mechanims.
#include <iostream>
#include <string>
#include <functional>
void printMyInt(int a)
{
std::cout << "This is your int " << a;
}
int main()
{
std::function<void(int)> f = printMyInt;
void (*const*foo)(int) = f.target<void(*)(int)>();
(*foo)(56);
}

How to pass Virtually Anything To A Function In C++ (or C)?

I need to pass something like a pointer that takes anything as a function parameter. You know, something without any predefined type or a type that can take anything like this:
void MyFunc( *pointer );
And then use it like:
char * x = "YAY!";
MyFunc(x);
int y = 10;
MyFunc(&y);
MyObj *b = new MyObj();
MyFunc(b);
And I don't want to use templates because I am mostly using C in my project.
Is there anything that can be used here except a function macro?
In C++, Boost.Any will let you do this in a type-safe way:
void func(boost::any const &x)
{
// any_cast a reference and it
// will throw if x is not an int.
int i = any_cast<int>(x);
// any_cast a pointer and it will
// return a null pointer if x is not an int.
int const *p = any_cast<int>(&x);
}
// pass in whatever you want.
func(123);
func("123");
In C, you would use a void pointer:
void func(void const *x)
{
// it's up to you to ensure x points to an int. if
// it's not, it might crash or it might silently appear
// to work. nothing is checked for you!
int i = *(int const*)x;
}
// pass in whatever you want.
int i = 123;
func(&i);
func("123");
You seem adverse to it but I'll recommend it anyway: if you're using C++, embrace it. Don't be afraid of templates. Things like Boost.Any and void pointers have a place in C++, but it is very small.
Update:
Well , I am making a small signals - slots - connections library to be
used with my gui toolkit. So that I can get rid of the Ugly WNDPROC. I
need these pointers for the connections.
If you need multi-target signals, Boost.Signals already provides a full and tested signals/slots implementation. You can use Boost.Bind (or std::bind, if you've got a C++0x compiler) to connect member functions:
struct button
{
boost::signal<void(button&)> on_click;
}
struct my_window
{
button b;
my_window()
{
b.on_click.connect(std::bind(&my_window::handle_click,
this, std::placeholders::_1));
}
void handle_click(button &b)
{
}
void simulate_click()
{
b.on_click(b);
}
};
If you only want a simple callback, Boost.Function (or std::function if you've got a C++0x compiler) will work well:
struct button
{
std::function<void(button&)> on_click;
}
struct my_window
{
button b;
my_window()
{
b.on_click = std::bind(&my_window::handle_click,
this, std::placeholders::_1);
}
void handle_click(button &b)
{
}
void simulate_click()
{
b.on_click(b);
}
};
You can use a function that takes a void*, but you must be aware of the pointer types that are not compatible with void*:
pointers to functions:
void MyFunc(void*);
MyFunc(&MyFunc); // WRONG
pointers to members:
void MyFunc(void*);
struct A { int x; };
MyFunc(&A::x); // WRONG
While these pointers are not compatible with void* (even with casting, on some compilers), they are themselves data. So you can pass a pointer to the pointer:
void MyFunc(void*);
void (*pfn)(void*) = &MyFunc;
MyFunc(&pfn); // ok
struct A { int x; };
int A::*px = &A::x;
MyFunc(&px); // ok
You can define the method as taking one void * argument. Of course, at that point, it's up to you to figure out what to do with the data (as far as accessing it or casting it.)
void MyFunc(void * ptr);
You could use:
void MyFunc( void* p){}
int g = 10;
MyFunc( (void*)&g );
void * is the way to do it. You can assign any pointer type to and from a void *. But to use the pointer in the called function, you'll have to know the type so you can create an appropriate local pointer or cast appropriately. You can encode a limited set of types as enum symbols, and perhaps use a switch to select type-specific behavior. But without a specific purpose or use-case, you might end up chasing your tail in a quest for generality for which C was never intended.
Another way would be to make a union to contain all the various types you know are needed.
typedef union {
int i;
char c;
float f;
} vartype;
Then if the value can carry around its own type-identifier, it becomes a tag-union or variant-record.
typedef struct {
enum type { INT, CHAR, FLOAT } type;
vartype var;
} varrec;

Callback to non-static method

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)