Sign in to follow this  
Servant of the Lord

C++ static class function + Function pointer issue

Recommended Posts

SDL has a feature that allows you to set up a filter, to filter incoming events. The problem is, the function requires a parameter that's a pointer to a function, and the function I want to pass it is a member of a class. My IDE(Dev C++) tells me that I can't pass member functions, unless the function is static, but inside the function that would be static, I call a function that's a memember of the class. In short:
API_Function(int *functionPointer);

class MyClass
{
    MySetupFunction();
    MyOtherFunction();
    
    MyCallback();
    MyStaticCallback();
};

MySetupFunction()
{
    API_Function(MyCallback); //<-- Invalid: cannot convert 'int (MyClass::*)(params)' to 'int (*)(params)'
    API_Function(MyStaticCallback); //<-- Valid
}

MyCallback()
{
    MyOtherFunction(); <-- Valid
}

MyStaticCallback()
{
    MyOtherFunction(); <-- Invalid: cannot call member function 'MyClass::MyOtherFunction() without object
    this->MyOtherFunction(); <-- Invalid: `this' is unavailable for static member functions
}
I can't make my callback function from outside of the class either, becuase it calls class functions, nor can I pass a pointer to my class as a parameter, becuase that's not part of the API function. I suppose I could have a global pointer to the class, and set it after creating the class, but that seems sloppy. How would you go about this? Is there any way to get a pointer to the calling class from a static member function? I thought for sure the 'this' keyword would work, but I guess not. Alternatively, is there anyway to cast a member function to a static function when passing it to the API as a function pointer? There will only ever be one instance of the class at one time, if that helps any. I apreciate any help you can offer, if only a few keywords to google.

Share this post


Link to post
Share on other sites
Are you familiar with Singleton pattern?

If you are not, shortly all you need to do is to create inside your class a static pointer to it self, initialize it in global scope to NULL,use assert(static pointer)in class constructor and set pointers address to this.Destructor is reverse process.Once you have done that, you can call:

pSingleton->AnyMemberFunction();

regards,
Savage

Share this post


Link to post
Share on other sites
There is no way to do this without a global of some sort. Best you can do is to make the global local to a single file then, inside an anonymous namespace.

@SavageTSDN

Singleton is unnecessary here.

It is unnecessary pretty much everywhere, but what can 1 programmer do [sad]

Share this post


Link to post
Share on other sites
Quote:
Original post by SavageTSDN
Are you familiar with Singleton pattern?


Relevant reading

--

No, there's no way to get a pointer to the class from a static member unless you pass one in. That's the whole reason that you can get away with using a pointer-to-static-member as if it were a function pointer (as opposed to a pointer-to-member, cf C++ FAQ Lite).

What parameters does the callback take? In particular, does it take a void*? If so, then use that to pass in a relevant object, as in my recent, similar thread (SiCrane's response, third reply). (EDIT: A quick Google suggests this is a no go :-( )

EDIT: Goodness, I'm slow.

Share this post


Link to post
Share on other sites
Thanks guys, I googled 'Singleton pattern' and used that. If merely one of my classes has a pointer to itself, I don't think it'd be going overboard with singletons, and it's pretty clean looking as well.

What I'm doing now:
API_Function(int *functionPointer);

class MyClass
{
static MyClass *Self;

MySetupFunction();
MyOtherFunction();
MyStaticCallback();
};

MyClass *MyClass::Self = NULL;

MyClass::MyClass()
{
Self = this;
}

MySetupFunction()
{
API_Function(MyStaticCallback);
}

MyStaticCallback()
{
assert(MyClass::Self);
Self->MyOtherFunction();
}

It works. Is there any reason why I shouldn't do it like this? Upon reading rip-off's reply, I could've made it a global in the class's cpp file. Hadn't thought of that, I was thinking of uglier method: (A global, with Set/Get functions)
MyClass myClass;
SetClassPointer(&myClass);
//Inside the static class function:
MyClass *myclass = GetClassPointer();

Which was why I posted looking for a cleaner solution.

Thanks for the help guys.

Share this post


Link to post
Share on other sites
Quote:
Original post by Servant of the Lord
Thanks guys, I googled 'Singleton pattern' and used that. If merely one of my classes has a pointer to itself, I don't think it'd be going overboard with singletons, and it's pretty clean looking as well.

What I'm doing now:
*** Source Snippet Removed ***
It works. Is there any reason why I shouldn't do it like this? Upon reading rip-off's reply, I could've made it a global in the class's cpp file. Hadn't thought of that, I was thinking of uglier method: (A global, with Set/Get functions)
MyClass myClass;
SetClassPointer(&myClass);
//Inside the static class function:
MyClass *myclass = GetClassPointer();

Which was why I posted looking for a cleaner solution.

Thanks for the help guys.


Read this topic,it might clear some things to you:

http://www.thescripts.com/forum/thread737451.html

Savage

Share this post


Link to post
Share on other sites
Quote:
Original post by SavageTSDN
Read this topic,it might clear some things to you:

http://www.thescripts.com/forum/thread737451.html

Savage


Singletons are globals. If you are going to use a global, don't be shy. This is what I would write:


// header file

class MyClass
{
MySetupFunction();
MyOtherFunction();

MyCallback();
static int MyStaticCallback( SDL_Event * );
};

void setupCallBack( std::auto_ptr<MyClass> );

// source file

namespace {
std::auto_ptr<MyClass> callbackPtr;
}

void setupCallBack( std::auto_ptr<MyClass> ptr )
{
callbackPtr = ptr;
}

int MyClass::MyStaticCallback( SDL_Event *event )
{
assert(callbackPtr.get());
return callbackPtr->MyCallback(event);
}


Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Quote:
Original post by SavageTSDN
Read this topic,it might clear some things to you:

http://www.thescripts.com/forum/thread737451.html

Savage


Singletons are globals. If you are going to use a global, don't be shy. This is what I would write:
*** Source Snippet Removed ***


Yes they are globals,but globals defined in a namespace(yes,I know that we can define global also in a namespace).Also when multithreading problem arises you cannot use just pure globals,but you can use singleton with locking..Singleton is somehow more elegant,and more reliable if you ask me.

Savage

Share this post


Link to post
Share on other sites
I'm going to stick with what I currently have. Using static MyClass *Self inside the class as a private member looks cleaner to me than a global, and easier to read.(To me at least)

The only drawback is if a second one of my classes is constructed, the static pointer wouldn't function as planned, but it's easy enough to protect against that by a flag to check against (Something like bool ClassActive), or even checking if the pointer is no longer NULL.

Thanks for your help guys, I was at a loss of what to do.

Share this post


Link to post
Share on other sites
Quote:
Original post by Servant of the Lord
I'm going to stick with what I currently have. Using static MyClass *Self inside the class as a private member looks cleaner to me than a global, and easier to read.(To me at least)

The only drawback is if a second one of my classes is constructed, the static pointer wouldn't function as planned, but it's easy enough to protect against that by a flag to check against (Something like bool ClassActive), or even checking if the pointer is no longer NULL.

Thanks for your help guys, I was at a loss of what to do.


If you create another instance of your class assertion would fail in constructor.
Also,if you just used a simple global,it members would probably get owerwriten when you use second instance,therefore singleton is more safer.

regards,
Savage

Share this post


Link to post
Share on other sites
Quote:
Original post by SavageTSDN
Yes they are globals,but globals defined in a namespace(yes,I know that we can define global also in a namespace).Also when multithreading problem arises you cannot use just pure globals,but you can use singleton with locking..Singleton is somehow more elegant,and more reliable if you ask me.


Multi-threading goes beyond mere locking. If you want proper multi-threading, then the chances are you are going to have to change your code to fit a concurrent paradigm. In any case, you can perform locking on globals. Singletons do not magically allow better locking.

Quote:

Also,if you just used a simple global,it members would probably get owerwriten when you use second instance,therefore singleton is more safer.


Not true. Remember, it is the Singleton that imposes this rather arbitrary "there can only be one" rule. A normal class can have many instances and none of them overwrite each others members.

In any case, have you ever accidentally created an object when you didn't mean to?

Me neither.

Food for thought.

Share this post


Link to post
Share on other sites
You suffer from low cohesion. Your class, whatever it is supposed to be, is handling unrelated responsibilities, which is causing you severe implementation challenges.

Separate your concerns. Design an event filtering system that doesn't need to call instance-dependent functions or access instance data, then separately implement a mapping system between events and object instances (including multiple object instances).

Happy hacking.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this