I'm trying to create a struct that have 2 function, which may be rewritten if needed later. The functions are: onClicked() and onClickedRight(). The code for the struct:
typedef struct {
QString text;
QString infoText;
QUrl iconSrc;
QColor iconColor;
void (*onClicked)() = nullptr;
void (*(*onClickedRight))() = &onClicked; // by default, execute the same function from onClicked()
} ConfigButton;
How I'm trying to execute these functions:
ConfigButton b;
...
// test if click funtion has been defined, to execute it
if (b.onClicked)
b.onClicked(); // this one work just fine
...
if (*(b.onClickedRight))
(*(b.onClickedRight))(); // this one crashed
Is it even possible? Am I missing something?
When onClicked is a function, both &onClicked and onClicked evaluate to the same thing -- a pointer to the function.
If you want to create a pointer to a function pointer, you need a pointer to a function as a variable first.
However, given your usage, you need just a pointer to a function.
typedef struct {
QString text;
QString infoText;
QUrl iconSrc;
QColor iconColor;
void (*onClicked)() = nullptr;
void (*onClickedRight)() = onClicked;
} ConfigButton;
and
if ( b.onClickedRight)
b.onClickedRight();
I think you can still solve your issue with a pointer to a function pointer, yet it is a bit clumsy, since you have to call this pointer-pointer in a different manner than you do with a "normal" function pointer. The call would look like (*(aButton.onRightClick))(), and you need to let onRightClick point to a pointer object pointing to a function rather than assigning the function directly.
I suppose you are looking for a way to define that onRightClick shall by default "inherit" the behaviour of onClick, unless the user overrides this and assigns a different behaviour to onRightClick. I see two requirements that a possible solution shall fulfill:
1) If onRightClick did not get overridden, it shall inherit every change made to onClick
2) If onRightClick gets overridden, it gets decoupled from onClick.
You can solve this with "simple" function pointers by assigning onRightClick a function that simply calls the one assigned to onClick. The following code shows this for C++; the approach can be transferred to C (though you then need to pass the "this" to the function calling onClick:
void defaultOnClick() {
std::cout << "defaultOnClick" << std::endl;
}
void otherClick() {
std::cout << "otherClick" << std::endl;
}
void rightClick() {
std::cout << "rightClick" << std::endl;
}
typedef std::function<void(void)> onClickFunctionType;
struct ConfigButton {
onClickFunctionType onClick = defaultOnClick;
onClickFunctionType onRightClick = [this](){ this->onClick(); };
} ;
int main() {
ConfigButton configButton;
std::cout << "default for both onClick and onRightClick (calling onClick)" << std::endl;
configButton.onClick();
configButton.onRightClick();
std::cout << "special click for onClick; 'inherited' by onRightClick" << std::endl;
configButton.onClick = otherClick;
configButton.onClick();
configButton.onRightClick();
std::cout << "special click for onClick; different one for onRightClick" << std::endl;
configButton.onRightClick = rightClick;
configButton.onClick();
configButton.onRightClick();
}
Output:
default for both onClick and onRightClick (calling onClick)
defaultOnClick
defaultOnClick
special click for onClick; 'inherited' by onRightClick
otherClick
otherClick
special click for onClick; different one for onRightClick
otherClick
rightClick
Answer adjusted, since OP has removed c from the tag list.
The code works as is. So you are doing something else wrong.
However, using a pointer to a pointer to a function in this way may not have the semantics that you want. If the structure gets copied to another structure, the onClickedRight member in the copy is not pointing to the onClicked pointer in its own instance. It is instead pointing to the onClicked pointer of the original instance.
a.onClickedRight = &a.onClicked;
b = a;
assert(b.onClickedRight == &a.onClicked); // Is this intentional?
What this means is that you have to be extra careful about how you use structures that contain pointers to its own members (and pointers to anything, really). You will probably need some kind of deep copy method (so, according to TRoT, you need a copy constructor, an assignment operator, and a destructor).
In any case, the C++ code is not really idiomatic. For myself, I would probably leverage virtual methods. The virtual method syntax can easily accommodate this use case.
struct ConfigButton {
QString text;
QString infoText;
QUrl iconSrc;
QColor iconColor;
virtual void onClicked() const = 0;
virtual void onClickedRight () const { onClicked(); }
};
struct Foo : ConfigButton {
void onClicked () const {
//...
}
};
If you follow this method, this will also work.
One possible approach is to have functions that implement the logic of firing the handler. You already have some logic (if (onClicked)) that the caller has to do anyway, so this minimizes the possibility of the caller making a mistake .
struct ConfigButton {
// ...
void Fire_OnClicked()
{
if ( onClicked )
onClicked();
}
void Fire_OnClickedRight()
{
if ( onClickedRight )
onClickedRight();
else
Fire_OnClicked();
}
private:
void (*onClicked)() = nullptr;
void (*onClickedRight)() = nullptr;
};
You could combine this with the std::function version, testing for empty instead of requiring "empty" to be represented by a lambda performing the default action. And if there are multiple handlers you want to have default fallback you could reduce boilerplate by making a template Fire function.
Another approach that might work would be to make a custom handler type with similar semantics to std::function but its () operator will perform a default action if no function has been set .
In the C language functions pointers are the only place where hiding pointers behind typedefs makes sense
https://godbolt.org/z/Gb_WEy
#include <stdio.h>
typedef int (*fptr_t)();
typedef struct
{
fptr_t fptr;
fptr_t *pfptr;
fptr_t **ppfptr;
fptr_t ***pppfptr;
}MYSTRUCT_t;
int foo(char *caller)
{
printf("Function name = %s, caller = %s\n", __FUNCTION__, caller);
return 0;
}
int main()
{
MYSTRUCT_t mystr;
mystr.fptr = foo;
mystr.pfptr = &mystr.fptr;
mystr.ppfptr = &mystr.pfptr;
mystr.pppfptr = &mystr.ppfptr;
printf("mystr.fptr=%p mystr.pfptr=%p func=%p\n", (void *)mystr.fptr, (void *)mystr.pfptr, (void *)&foo);
foo("foo");
mystr.fptr("mystr.fptr");
(*mystr.pfptr)("mystr.pfptr");
(*(*mystr.ppfptr))("mystr.ppfptr");
(*(*(*mystr.pppfptr)))("mystr.pppfptr");
}
Related
I want to make Dialog handler for my app that will contain pointer to method that will be invoked when user answer "yes" and pointer to method for "no" and the main problem that these methods can have various args or without it so i dont know how to declare this variable.
class Dialog
{
protected:
Dialog()
{
}
static Dialog* singleton;
public:
Dialog(Dialog &other) = delete;
void operator=(const Dialog &) = delete;
static Dialog *instance();
string question;
?? method_yes;
?? method_no;
static bool has_dialog();
static void clear();
};
Dialog* Dialog::singleton = nullptr;
Dialog* Dialog::instance()
{
if (singleton == nullptr) {
singleton = new Dialog();
}
return singleton;
}
bool Dialog::has_dialog()
{
return singleton != nullptr;
}
void Dialog::clear()
{
if (singleton)
{
delete singleton;
singleton = nullptr;
}
}
So there is my class for dialog with user, when i want to ask user something i do
auto yes = []()
{
ExitProcess(0);
};
Dialog::instance()->question = "Do you want to exit?";
Dialog::instance()->method_yes = yes;
And somewhere upper or whatever i have answer handling
if (Dialog::has_dialog())
// render question and buttons
// if pressed button yes
Dialog::instance()->method_yes();
Dialog::clear();
And what if for example i want to manage exit code so my lambda will be
auto yes = [](int code)
{
ExitProcess(code);
};
But then there is a new argument so i cant just use
void(*method_yes)();
for declaration
At the end of the day, C++ is a strongly typed language and you'll have to provide the set of expected possible arguments in your function signature.
Since you don't want that, there are some techniques to circumvent it so let's name a few:
The old (old old) void* trick from C. You declare your function pointer as
void (*fptr)(void* state);
and then you're free to interpret state however you wish in your fptr, e.g. if state==nullptr you can assume there are "no arguments". Note that this approach is not type safe and can cause a lot of headaches if users don't respect the agreed upon protocol.
You bundle all your state in your callable and your function pointer becomes something like std::function<void()>. This way you can write:
std::function<void()> fptr = [code]() { /* ... */ };
This is the nerfed version of the above, meaning your lambdas are now responsible for capturing the state you'd be passing to the function as arguments.
A pattern I'm using lately involves C++20 designated initializers like so:
struct Argument
{
std::optional<int> code;
std::optional<std::string> name;
std::optional<float> value;
};
void (*fptr)(Argument arg); // Argument is elastic, i.e.
// it can be formed as:
// {} -> no arguments
// {.code=1} -> 1 argument
// {.code=1, value=2.}-> 2 arguments
// etc
// Fields not mentioned default to
// nullopt, which means you have
// an easy way of telling them apart
int main ()
{
fptr = [](Argument arg) {
std::cout << arg.code.value_or(0) << std::endl;
std::cout << arg.name.value_or("no name") << std::endl;
std::cout << arg.value.value_or(42) << std::endl;
};
fptr({});
std::cout << "-------------\n";
fptr({.name="Garfield"});
std::cout << "-------------\n";
fptr({.code=3, .value=3.14});
std::cout << "-------------\n";
}
This is a type-safe alternative to (1). You declare the expected set of arguments in Argument but since they are optional you can call fptr({}) and mark everything as "non existent" (the no args case) or even initialize one or more arguments explicitly e.g. fptr({.code=3, .value=3.14}). Inside fptr you can inspect whether an optional variable is "filled" and this gives you the freedom to act accordingly (demo).
If all this still seems unattractive, I wrote a post some years ago on how to create overload sets out of lambdas. Essentially the technique allows you to write things like:
auto fptr = overload(
[]{ /*...*/ }, // A
[](int code) { /*...*/ }); // B
fptr(); // Calls A
fptr(22); // Calls B
Again this means that all possible solutions (sets of functions of different types) are known at compile time, but you dodge the pain of creating that set explicitly.
Finally I'd re-visit the design before resorting to such solutions, maybe a simpler path exists e.g. express the exit functions as a hierarchy and have a factory method to generate the active function at runtime or even reconsider why should an exit function be tweakable at runtime.
I am trying to write a templated wrapper class around a stateless lambda. Something like this:
template <class TFuncOp>
class Adapter
{
public:
void Op()
{
TFuncOp func; // not possible before C++20
func();
}
};
Since this isn't possible before default constructible lambdas arrive with C++20, I used this technique to make my class work: Calling a stateless lambda without an instance (only type)
So the final solution looks like this:
template <class TFuncOp>
class Adapter
{
public:
static TFuncOp GetOpImpl( TFuncOp *pFunc = 0 )
{
static TFuncOp func = *pFunc;
return func;
}
void Op()
{
GetOpImpl()();
}
};
template <class TFuncOp>
Adapter<TFuncOp> MakeAdapter(TFuncOp func )
{
// Removing the line below has no effect.
//Adapter<TFuncOp>::GetOpImpl( &func );
return Adapter<TFuncOp>();
}
int main()
{
auto adapter = MakeAdapter( [] { printf("Hello World !\n"); } );
adapter.Op();
return 0;
}
This code works on all major compilers (clang, gcc, msvc). But with one surprising discovery. Initialization (or lack thereof) of the static local instance of the lambda in GetOpImpl() has no effect. It works fine either way.
Can anyone explain how this works? Am I invoking UB if I use the static local instance of the lambda without initializing it?
In any case, accessing a nullptr is never a good idea as it is UB.
But we can see that typical implementations generate code which simply works. I try to explain why:
First, it has nothing to do with lambdas. It is simply the not needed using of a copy constructor on a class which has no data. As you have no data, the generated code will not access the passed object. In your case, you "copy" the object which the pointer TFuncOp *pFunc = 0 points to, which is a nullptr which will crash if the object must be accessed. As there is no data to access, a typical implementation will not genrate any code which will access the nullptr at all. But it is still UB.
The same works with all other types in the same way and has nothing special with a lambda!
struct Empty
{
void Do() { std::cout << "This works the same way" << std::endl; }
// int i; // << if you add some data, you get a seg fault
};
int main()
{
Empty* ptr = nullptr;
Empty empty = *ptr; // get seg fault here, because default copy constructor access the nullptr, but typically only if copy ctor needs to access!
empty.Do();
}
And a lambda which has no captured data, is an empty structure with a operator()().
That all is a answer why it seems to work.
Suppose that I have this code:
class MyClass
{
public:
void SomeFunction()
{
// Find somehow if this is first, second, or third call of a function in a main loop
// If the function is called first time create new variables that will be used just for this function call
}
};
MyClass myClassObject;
int main()
{
myClassObject.SomeFunction(); // First call
myClassObject.SomeFunction(); // Second call
myClassObject.SomeFunction(); // Third call
}
How can I know inside function what number of call is it?
Note that I will probably have 100 function calls placed in code. Also this should work in Visual Studio on Windows and Clang on Mac.
I had one workaround:
void SomeFunction(const char* indetifier = "address")
{
CheckAddress(indetifier); // This will check if address is stored. If it is not, create variables, if it is, if addresses matches use variables that are tied to that address.
}
I tried not to assign a new string to an "indetifier" and to let it to use default string ("address"). This of course didn't worked well as compiler will optimize "indetifier", so I was thinking that maybe a solution would be to disable optimizations for that variable, but I didn't because there should be some more elegant solution.
Also one thing came on my mind, maybe I could force inline a function and then get it's address, but this also seams like bad workaround.
I could also create new classes for every call but I would like to avoid this as there will be a lot of function calls and I don't want to think 100 different names.
If there is a way to create class object only at first call this would be awesome.
I hope that you understand what I want, sorry if something is not that clear as I am beginner coder.. :D
EDIT:
I can't use static for variables in a class because software that I am developing is a plugin that could have multiple instances loaded inside host and this will probably mess up the variables. I have tested static variables and if I create for example "static int value" anywhere and write something in it in one instance of a plugin this "value" will be updated for all instances of a plugin and this is not something that I want.
void SomeFunction()
{
// Find somehow if this is first, second, or third call of a function in a main loop
// If the function is called first time create new variables that will be used just for this function call
}
If the first call is to be tracked per object, then you need a member variable that keeps track of how many times SomeFuntion has been called for that object.
If the first call is to be tracked independent of objects, then you can use a static function variable that keeps track of how many times SomeFuntion has been called for that object.
I can't use static for variables in a class because software that I am developing is a plugin that could have multiple instances loaded inside host and this will probably mess up the variables. I have tested static variables and if I create for example "static int value" anywhere and write something in it in one instance of a plugin this "value" will be updated for all instances of a plugin and this is not something that I want.
So make a non-static counter?
class MyClass {
int count;
public:
MyClass () : count(0) { }
void SomeFunction () {
++ count;
// do stuff with 'count'
}
};
MyClass myClassObject;
int main () {
myClassObject.SomeFunction(); // First call
myClassObject.SomeFunction(); // Second call
myClassObject.SomeFunction(); // Third call
}
Or just pass it as a parameter...
class MyClass {
public:
void SomeFunction (int count) {
// do stuff with 'count'
}
};
MyClass myClassObject;
int main () {
myClassObject.SomeFunction(1); // First call
myClassObject.SomeFunction(2); // Second call
myClassObject.SomeFunction(3); // Third call
}
But I'm really wondering what you're actually trying to do, and I highly suggest sitting back and rethinking this whole thing, because there are a number of red flags / confusing points here...
If you're only interested in checking whether it's the first call, you can add a bool SomeFunction_first_call; to the MyClass, to act as a flag. The constructor sets the bool to true. MyClass::SomeFunction() uses the conditional check if (SomeFunction_first_call) /* ... */ to determine whether it's the first call, as follows:
class MyClass
{
bool SomeFunction_first_call;
public:
MyClass() : SomeFunction_first_call(true) {}
void SomeFunction()
{
if (SomeFunction_first_call)
{
// This code only executes on first call.
do_something();
// Successfully handled first call, set flag to false.
SomeFunction_first_call = false;
}
// This code always executes.
do_something();
}
};
Similarly, if you're only concerned about the first HOWEVER_MANY_CALLS calls, where HOWEVER_MANY_CALLS is a number, you can use something like this:
#include <cstdint>
class MyClass
{
uint8_t SomeFunction_calls;
public:
MyClass() : SomeFunction_calls(0) {}
void SomeFunction()
{
// This segment will be executed until (SomeFunction_calls == HOWEVER_MANY_CALLS).
// After this, the segment will be skipped, and the counter will no longer increment.
if (SomeFunction_calls < HOWEVER_MANY_CALLS)
{
// This code only executes on first HOWEVER_MANY_CALLS calls.
do_something();
// Increment counter.
++SomeFunction_calls;
}
// This code always executes.
do_something();
}
};
Make sure to use the appropriately signed variable for the number of calls that need special handling (i.e. uint8_t for 0..255, uint16_t for 256..65,535, etc.). If different instances of MyClass will need to keep track of a different number of calls, then use a non-type template parameter to indicate this, and optionally, a defaulted typename to indicate what type the counter should be.
#include <cstdint>
template<uint64_t N, typename T = uint64_t>
class MyClass {
T SomeFunction_calls;
...
void SomeFunction()
{
if (SomeFunction_calls < N) {
...
}
...
}
};
In this case, a MyClass<4> will have special treatment for the first 4 calls to SomeFunction(), a MyClass<4444444444444444444> will have special treatment for the first 4,444,444,444,444,444,444 calls, and so on. The counter will default to uint64_t, as that should be large enough to hold the value; when only a smaller number of calls need special treatment, you can specify a smaller type, such as MyClass<4, uint8_t> or MyClass<444444444, uint32_t>.
In C++ you can use the static keyword in a local variable context to create the object only once at the first call:
#include <iostream>
struct MyObject {
MyObject() {
std::cout << "Creating instance " << this << "\n";
};
};
void foo() {
static MyObject my_instance;
std::cout << "... inside function foo ...\n";
}
int main(int argc, const char *argv[]) {
std::cout << "About to call foo...\n";
foo();
std::cout << "... second call ...\n";
foo();
std::cout << "... third call ...\n";
foo();
return 0;
}
With the above code you will notice that only on object MyObject will be created, on the first call to foo.
Note that if your function is a template then for each instantiation of the template you will get another distinct static variable. For example with:
template<int N>
void foo() {
static MyObject my_instance;
std::cout << "... inside function foo ...\n";
}
the all the calls to foo<1>() will use the same variable but calling instead foo<2>() will access another copy of the function (another instantiation of the function template), that will have its own distinct static variable created on the first call to foo<2>(). All static variables that have been initialized will be destroyed after the end of main when the program terminates.
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)