C++ Function call as a parameter, not working - c++

http://pastebin.com/CsViwQFg
I'm using an SDK known as DragonFireSDK and there's a function called TouchAdd() that let's me add a function as a parameter (in this case: MoveLeft() and MoveRight()).
The only problem is, if the function is in a class (in this case, the Player class), I get the following errors:
Player *player;
void AppMain()
{
player = new Player(20,20,10);
tleft = TouchAdd(0,0,180,480,player->MoveLeft,0);
tright = TouchAdd(180,0,180,480,player->MoveRight,0);
}
The error:
error C3867: 'Player::MoveLeft': function call missing argument list; use '&Player::MoveLeft' to create a pointer to member
error C3867: 'Player::MoveRight': function call missing argument list; use '&Player::MoveRight' to create a pointer to member

If you want to pass function as a parameter then syntax is &Player::MoveLeft; as it is not bound to any object such as player.

The DragonFireSDK appears to want a "C" callable function and you're trying to pass a member function (though not using the right syntax). I think you'll need to do something like:
Player *player;
extern "C"
int PlayerMoveLeft(int id, int event, int x, int y)
{
// do something - I'm not sure what might be possible
// to get a pointer or a reference to the player object
// hopefully one or more parameters passed to this callback
// will have the information you need to do that
// or if you only have one global player, you're set -
// just use it
Player* player = /* ??? */;
player->MoveLeft( id, event, x, y); // or whatever needs to be passed
return 0;
}
extern "C"
int PlayerMoveRight(int id, int event, int x, int y)
{
Player* player = /* ??? */;
player->MoveRight( id, event, x, y); // or whatever needs to be passed
return 0;
}
void AppMain()
{
player = new Player(20,20,10);
tleft = TouchAdd(0,0,180,480,PlayerMoveLeft,0);
tright = TouchAdd(180,0,180,480,PlayerMoveRight,0);
}
Note that even though a static member function will often work (since there's no 'hidden' this pointer passed in, strictly speaking you should use non-member extern "C" functions.

Since the function signature of TouchAdd (taken from here) is
int TouchAdd(int x, int y, int width, int height, int (*callback)(int id, int event, int x, int y), int id);
the expected function must be a free function, eg:
int myCallback(int id, int event, int x, int y){
// do your stuff
}
void AppMain(){
tLeft = TouchAdd(....,&myCallback,...);
}
You can't pass a member function pointer (&Player::MoveX), since that function needs to be called on an object of that class (Player). So you need to use a work-around for that:
Player* player;
int PlayerMoveLeft(int id, int event, int x, int y){
return player->MoveLeft(id,event,x,y);
}
int PlayerMoveRight(int id, int event, int x, int y){
return player->MoveRight(id,event,x,y);
}
void AppMain(){
player = new Player(20,20,10);
tLeft = TouchAdd(...,&PlayerMoveLeft,...);
tRight = TouchAdd(...,&PlayerMoveRight,...);
}
}

It seems like id is the custom parameter that gets passed to the callback. If you only have 32-bit targets (and it seems like DragonFireSDK is meant only for iPhone, so I guess the answer is yes), you can cast it to Player* to bind to the player instance.
int PlayerMoveLeft(int id, int event, int x, int y)
{
Player* player = reinterpret_cast<Player*>(id);
return player->MoveLeft(event, x, y);
}
int PlayerMoveRight(int id, int event, int x, int y)
{
Player* player = (Player*)id;
return player->MoveRight(event, x, y);
}
void AppMain()
{
Player* player = new Player(20,20,10);
tleft = TouchAdd(0,0,180,480,PlayerMoveLeft,(int)player);
tright = TouchAdd(180,0,180,480,PlayerMoveRight,(int)player);
}
Even if that doesn't work, or you don't want to use kinda-ugly type casts, you can always have a global or static object with lookup tables. Making PlayerMoveLeft and PlayerMoveRight static members of the Player class may also look nicer, and I think it should play well with TouchAdd().

tleft = TouchAdd(0,0,180,480,player->MoveLeft,0);
tright = TouchAdd(180,0,180,480,player->MoveRight,0);
You're not passsing arguments to MoveLeft and MoveRight functions. I suppose they're function call as the title of your topic says, so you must pass arguments as well IF they take arguments.
If they're don't take argument, then do this:
tleft = TouchAdd(0,0,180,480,player->MoveLeft(),0);
tright = TouchAdd(180,0,180,480,player->MoveRight(),0);
If they're NOT function calls, instead you want to pass the member function pointers, then do this:
tleft = TouchAdd(0,0,180,480, &Player::MoveLeft,0);
tright = TouchAdd(180,0,180,480, &Player::MoveRight,0);
You also need to pass the instance so that member functions can be invoked later on.
It would be better if you let us know the signature of TouchAdd function. So that we can answer more specifically.

Related

Passing class by reference doesn't change original

I have a class that handles rendering sprites, which has a Ball and Gun objects on it, sets their sprites, and renders them every frame. I want to pass in that ball object to gun, so that gun can fire when a user presses space (input is handled on gun). I tried pointers, and now passing by reference, but when I change it after passing it in it doesn't affect the original. In my main class I call gun.init(&ball) that I'll show here. Gun has a variable Ball mBall.
class Gun : public GameObj
{
public:
Gun()
:GameObj(), mWaitSecs(0)
{}
void Update();
void Init(Ball &ball); //init function that passes in ball?
private:
float mWaitSecs; //delay after firing beforeo you can move/fire
Ball mBall;
};
void Gun::Init(Ball &ball) {
mBall = ball;
}
[..] but when I change it after passing it in it doesn't affect the original.
Frankly, you have a basic misunderstanding. And to clear that up, I have to take a small detour.
Pass by value
void foo_value(int x) { x += 42; }
calling this function via
int y = 50;
foo_value(y);
will not change the value of y.
Pass by reference
void foo_ref(int& x) { x += 42; }
calling this function will modify y:
int y = 50;
foo_ref(y);
assert(y == 50+42);
Rebinding references
You cannot rebind references. That's why you cannot not initialize a reference:
int& y; // error
int x;
int& y = x; // ok
Once you have a reference you cannot make it refer to something else. You cannot "reassign" the reference:
int x = 0;
int& ref = x;
int y = 42;
ref = y; // same as x = y;
after the last line, ref is still a reference to x.
Your code
You do pass ball by reference, but your member mBall is not a reference. mBall is a copy of the ball refered to by ball. An example similar to your code is
void foo_copy_from_ref(int& x) {
int mx = x;
mx = 42;
}
Modifying a copy has no effect on the original, no matter if you made the copy from a reference.
You can have a reference to a Ball as member, but you have to initialize it in the constructor and you cannot make it refer to a different Ball later.

How to Pass Struct Data Member into Function

I want to be able to pass a struct member into a function:
struct threeBuckets {
int bucketA;
int bucketB;
int bucketC;
};
threeBuckets allCombinations[512000] = {{0,0,0}};
int totalCombinations = 1;
int counter = 0;
//note that pourer, receiver, and other are one of the struct members (bucketA, bucketB, and bucketC)
void pour(pourer, receiver, int receiverCap, other) {
int finalTriple[3];
allCombinations[totalCombinations].bucketA = allCombinations[counter].bucketA;
allCombinations[totalCombinations].bucketB = allCombinations[counter].bucketB;
allCombinations[totalCombinations].bucketC = allCombinations[counter].bucketC;
allCombinations[totalCombinations].receiver = allCombinations[totalCombinations].receiver + allCombinations[counter].pourer;
allCombinations[totalCombinations].pourer = 0;
if (allCombinations[totalCombinations].receiver > receiverCap) {
allCombinations[totalCombinations].pourer = allCombinations[totalCombinations].pourer + allCombinations[totalCombinations].receiver - receiverCap;
allCombinations[totalCombinations].receiver = receiverCap;
}
finalTriple[0] = allCombinations[totalCombinations].bucketA;
finalTriple[1] = allCombinations[totalCombinations].bucketB;
finalTriple[2] = allCombinations[totalCombinations].bucketC;
//some more irrelevant code
}
As I've hopefully made clear, the parameters pourer, receiver, and other are bucketA, bucketB, and bucketC (in no particular order, the order does change depending on when I call the function.) There are several places where I want to modify the instance
allCombinations[totalCombinations].pourer
for example. How do I use the struct member as a parameter, and what type do I use to specify it?
Note: I'm mostly a beginner and am new to StackOverflow, so if anything else I'm doing is wrong, please feel free to tell me.
Note 2: If any of you do or have done USACO, you might recognize this problem as the milk3 training gateway problem. This might aid you if you don't know what I'm doing here.
It sounds like you need to use pointer to member variable for the argument types in pour.
void pour(double threeBuckets::(*pourer) ,
double threeBuckets::(*receiver),
int receiverCap,
double threeBuckets::(*other)) {
...
}
In the function, change the use of
allCombinations[totalCombinations].pourer
allCombinations[totalCombinations].receiver
allCombinations[totalCombinations].other
by
allCombinations[totalCombinations].*pourer
allCombinations[totalCombinations].*receiver
allCombinations[totalCombinations].*other
respectively.
At the point of calling the function, use:
pour(&threeBuckets::bucketA,
&threeBuckets::bucketB,
0, // Any appropriate value
&threeBuckets::bucketC);
Another option that is worth considering is:
Change threeBuckets to use an array.
Change the arguments to pour to be indices to the array.
struct threeBuckets {
int buckets[3];
};
void pour(int pourerIndex ,
int receiverIndex,
int receiverCap,
int otherIndex)) {
...
}
Then, instead of using
allCombinations[totalCombinations].pourer
allCombinations[totalCombinations].receiver
allCombinations[totalCombinations].other
use
allCombinations[totalCombinations].buckets[pourerIndex]
allCombinations[totalCombinations].buckets[receiverIndex]
allCombinations[totalCombinations].buckets[otherIndex]
Of course, change the call to use indices.
pour(0,
1
0, // Any appropriate value
2);

OpenCV mouse calls?

I am using cvSetMouseCallback to track mouse clicks. However I need to pass in more than one argument to the function that is passed in to cvSetMouseCallback. However cvSetMouseCallback only accepts one parameter to pass in data to the function it calls. How I would I do this with more than one argument?
For example:
cvSetMouseCallback ("Window", function, argumentPassedintofunction);
void function (int event, int x, int y, int flags, void* param, CvRect *drawnRect, IplImage *skinSegment, IplImage *colourSpaceImg, CvHistogram *skin, IplImage *planes [])
{
}
So as you see, I need to pass in more than one parameter to function () but cvSetMouseCallback only allows one argument to be passed in.
I DO NOT WANT TO ACCESS THE OS FOR MOUSE CALLS (so not handles and any of that, I strictly want to stick to opencv)
Also making the arguments global variables isn't an option.
You can make function take in a struct which contains all the parameters.
typedef struct func_params_ {
int event;
int x;
int y;
int flags;
void* param;
CvRect* drawnRect;
......
} func_params

How to pass a class method as a GLUT callback?

I know this thing works:
void myDisplay()
{
...
}
int main()
{
...
glutDisplayFunc(myDisplay)
...
}
so I tried to include myDisplay() function to a class that I made. Because I want to overload it in the future with a different class. However, the compiler complains that
argument of type 'void (ClassBlah::)()' does not match 'void(*)()' .
Here is the what I try to make:
class ClassBlah
{
....
void myDisplay()
....
}
......
int main()
{
...
ClassBlah blah
glutDisplayFunc(blah.myDisplay)
...
}
Does anybody knows how to fix this problem?
Firstly, there is an implicit "this" pointer in non-static member functions, so you'll need to change your void myDisplay() in ClassBlah to be static. It's awkward to work around this limitation, which is why the C++ faq lite says don't do it
Then, you should be able to pass the functions as ClassBlah::myDisplay.
Depending on your motivation for overloading (ie are you going to hotswap implementations in and out at runtime, or only at compile time?) you might consider a utility "handler" static class that contains a pointer to your base class, and delegates responsibility through that.
I ran into this problem writing a C++ Glut engine myself. Here's how I worked around it:
I placed these at the top of my program.cpp / main.cpp
// Function prototypes
void doRendering( void );
void processMouse( int, int ) ;
void processMouseClick(int button, int state, int x, int y);
void keyboardInput(unsigned char c, int x, int y);
Assign these functions to glut's callbacks here:
glutDisplayFunc(doRendering);
glutIdleFunc(doRendering);
glutPassiveMotionFunc(processMouse);
glutMotionFunc(processMouse);
glutMouseFunc(processMouseClick);
glutKeyboardFunc(keyboardInput);
Create my own class which handles these on its own and then make the contents of our static functions simply call methods on the instance of this class. Your main function should create a new instance of the class in main (in my case... App *newApp).
void doRendering( void )
{
newApp->updateScene();
newApp->drawScene();
}
void processMouse(int x, int y)
{
newApp->processMouse(x, y);
}
void processMouseClick(int button, int state, int x, int y)
{
newApp->processMouseClick(button, state, x, y);
}
void keyboardInput(unsigned char c, int x, int y)
{
newApp->keyboardInput(c, x, y);
}
Hope that explains it.
My way to solve this is simple:
First make a pointer before main function.
At the beginning of the the main function set pointer to instance of your class.
Then in new defined function for rendering, You can acces your object with global pointer.
/**
Class argon is defined in external header file.
*/
Argon *argonPtr;
void renderScene();
int main()
{
Argon argon;
argonPtr = &argon;
glutDisplayFunc( render );
}
void render()
{
RenderStuff();
argonPtr->Render();
}
Hope it works for You, for me it does.
You can use Boost bind for member functions, for example creating a thread on a member function:
class classA
{
public:
void memberThreadFunc(int i);
};
void main()
{
classA a;
boost::thread( boost::bind(&classA::memberFunc, &a, 123) );
}
You can't. glutDisplayFunc takes a parameter of type void(*)(), not void (ClassBlah::)(). Unless you're willing and able to alter the source of glut, you're out of luck.
Many C APIs that use callbacks pass a user-specified void* parameter to the callback, which you can use to store a pointer to your class. You can then pass a free function which casts the user data to a class pointer and then calls the member function. However, the way glut is designed doesn't allow that.

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)