Call member function out of a static function - c++

I just started messing around with Lua. Everything works just fine, but I've got a problem.
When I'm using "lua_register", I have to pass a static function as the third parameter. But the problem is, that I want to call a member function from that static function. But the compiler says, that this is not possible.
Do you know a way how to do that?

Either make member function static or pass an instance of the class to your static function and call its member.

Related

invalid use of non-static member function

In my Qt application I wish to be able to add a tab to a non-static QTabWidget when the user presses a shortcut. Normally I would implement it like this:
File.addAction("Settings", openSettings, Qt::ALT + Qt::Key_S);
where File is a QTabWidget and openSettings is a static method. The only issue with that is that it only works for static methods, and the issue with that is that I can't access a non-static variable in a static method. As such I figured that since Qt asks for the function to be a static function I can instantiate a static std::function<> object as such:
static std::function<void(void)> openSettings_ = []() { openSettings; };
and call it as such
File.addAction("Settings", openSettings_, Qt::ALT + Qt::Key_S);
The issue with this is that it generates the error:
Error: invalid use of non-static member function 'void window::openSettings()'
My reasoning for this is that I am familiar with C and assumed that what Qt calls a functor is almost the same as a function pointer that pretty much is an object. As such, I assumed that if I were to instantiate a static object of type std::function that pointed to / executed a non-static function I would get around this issue, which is clearly not the case. How would I go about doing this, seeing as my current thought process is wrong?
First, the immediate error is raised because you're not actually calling the function. You must call it: openSettings();.
However, this won't work. openSettings is non-static member function. All such normal member functions take an implicit this pointer to the object on which they're being invoked. This means that one cannot directly invoke the openSettings function without an object on which to invoke it. But this is not captured by the lambda you've written, meaning there's no such object.
This can be fixed by capturing this in the lambda, such as auto openSettings_ = [this]() { this->openSettings(); };
But on the other hand, this function is acting like a slot. You should attach the signal you're interested in directly to the signal using the standard signal/slot syntax, rather than writing the separate functor. That would be something like this.
File.addAction("Settings", this, &(decltype(*this))::openSettings, Qt::ALT + Qt::Key_S);
(Note that I'm using decltype because I'm not sure what type *this is. You can substitute with the name of the class.)

(C++) Pass 'this' to a static method as a default parameter

Clearly doing something like static void DoSomething(ClassPointer* MyPtr = this) wouldn't work, because a static method has no this, however when I call this DoSomething I am always passing the this from the class calling it, I'd like to not have to put it in every time.
If there was some way to get a reference to the class calling that static method from inside the method itself then that would work, but AFAIK there isn't.
What options do I have available?
Write a macro
#define DoSomethingX(...) DoSomething(this, __VA_ARGS__)
And call
StaticFunctionClass::DoSomethingX(par1, par2);
If you need the context of the requesting object to be passed as a reference, I would consider having the method be a non-static instance method. This way, you can reference the other instance members of the class within the method. If the behavior changes depending on the subclass class, perhaps you could use a virtual method that can be overridden.

invalid use of non-static member function while setting a v8 function

i have used v8 inside a class. Createcontext method is also inside a wrapper class. when i try to set global and map it to print function which is also inside the same class, i am getting error
invalid use of non-static member function
the line i used to set the method is
global->Set(v8::String::NewFromUtf8(isolate,"print"), v8::FunctionTemplate::New(isolate,this -> print));
can someone please explain me why this error happens and how to resolve it
The function you pass to FunctionTemplate::New must be static. Hence try making the print function inside your class static.

Is there any way to change the scope of a callback without changing the paramaters?

I am using SDL2_mixer library, but I believe that the question should hold for the general case also.
Currently, a function that I would like to use, Mix_HookMusicFinished(void (*music_finished)(void)) has a set callback to the global scope for a C style function. However, I would like to have that callback be set to a member function within my own class void CMusic::musicFinished() without having the need for a function in global scope.
Is there anyway to do this? Something like Mix_HookMusicFinished(musicFinished) would be great, but that directly has an error of argument of type "void (CMusic::*)()" is incompatible with parameter of type "void (*)()"
You need to make a "wrapper" function. However, the problem here is that you also need to be able to find the CMusic object that you want to "finish" - this is really what the crux of
argument of type ... is incompatible with ...
is all about. Since there is no way to pass a parameter to the musicFinished object, you will need some other way of "finding" the CMusic object.
If we assume there is a way to do that, then something like this would work:
class CMusic
{
...
public:
...
static void musicFinishedWrapper();
void musicFinished();
...
};
void CMusic::musicFinishedWrapper()
{
CMusic* music = getTheMusicSomehow(); // No idea how you do this - depends on your code.
music->musicFinished();
}
The reason you have to have a CMusic object is that your musicFinished expects a (hidden) this pointer argument - which is the value in music in my little function.
You could move musicFinished to your CMusic class and declare it as a static class method. static class methods aren't called on an object; they therefore don't have an implicit argument to specify the value of the this pointer, and they therefore can have the same signature as freestanding functions. You additionally can make it private to prevent anything but CMusic from using it.
However, since your musicFinished method currently works as a freestanding function and therefore probably doesn't need access to CMusic's protected or private members, and since your efforts to limit its scope presumably means that you don't want other things to call it, I personally would leave your musicFinished function as freestanding but declare it as static (or move it to an anonymous namespace, if you prefer) within the CMusic source (.cpp or .cc) file. Doing so would restrict its scope to the source file (the "compilation unit"). An advantage over a private, static class method is that it does not need to be exposed at all in a header file, so it is in some sense more private.

How do you pass a non-static function as a callback?

I'm currently working with Qt and a graphics engine and during the init of the QGLWidget instance I need to pass a few function pointers to my engine.
The function looking for callbacks is:
virtual void Buffer::CreateCustom( byte* getsize, byte* makecurrent)
Qt provides a makeCurrent function however it is neither byte* nor static.
I could write a tiny wrapper function like so:
void _stdcall MakeCurrent(void)
{
QGLContext::makeCurrent();
}
But its only meant to be called from within an instance of GLWidget. I tried to create a class member wrapper function like so:
void _stdcall LEWidget::leMakeCurrent(void)
{
makeCurrent();
}
But you can only provide function pointers on static member functions. If I do that I get the following error:
error C2352: 'QGLWidget::makeCurrent' : illegal call of non-static member function. A nonstatic member reference must be relative to a specific object.
See this question, I think it is pretty much what you want to do:
How do I implement a callback in C++?
You can't. That's what std::function exists for. You need to either change your interface to use std::function, get lucky and find some kind of void* context argument, or give up.
This is because it is impossible to tell(from the compiler's POV) which this pointer should be pass into that function when that callback is called. If you really really want to pass in a pointer, you'll have to use assembly.