Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ class member function pointer to function pointer

I am using luabind as my lua to C++ wrapper. Luabind offers a method to use my own callback function to handle exceptions thrown by lua, set_pcall_callback(). So I paraphrased an example from the documentation, the changes being the logger->log() function and putting the function in a class called 'Engine', so instead of it being a regular global function it is now a member function, which is where my problem seems to be.

Here are the relevant code snips:

class Engine //Whole class not shown for brevity
{
public:
    Engine();
    ~Engine();
    void Run();
    int pcall_log(lua_State*);
private:
    ILogger *logger;
};

Engine::Run()
{
lua_State* L = lua_open();
luaL_openlibs(L);
open(L);
luabind::set_pcall_callback(&Engine::pcall_log); //<--- Problem line
//etc...rest of the code not shown for brevity
}

int Engine::pcall_log(lua_State *L)
{
lua_Debug d;
lua_getstack( L,1,&d);
lua_getinfo( L, "Sln", &d);
lua_pop(L, 1);
stringstream ss;
ss.clear();
ss.str("");
ss << d.short_src;
ss << ": ";
ss << d.currentline;
ss << ": ";
if ( d.name != 0)
{
    ss << d.namewhat;
    ss << " ";
    ss << d.name;
    ss << ") ";
}
ss << lua_tostring(L, -1);
logger->log(ss.str().c_str(),ELL_ERROR);
return 1;
}

Here is what the compiler says during compilation:

C:\pb\engine.cpp|31|error: cannot convert 'int (Engine::*)(lua_State*)' to 'int (*)(lua_State*)' for argument '1' to 'void luabind::set_pcall_callback(int (*)(lua_State*))'|

So it seems that the error is that the function expects a regular function pointer, not a class member function pointer. Is there a way to cast or use an intermediate function pointer to pass to the set_pcall_callback() function?

Thank you!

like image 403
Brian Avatar asked Aug 02 '11 07:08

Brian


People also ask

Can we call member function using this pointer?

You can use pointers to member functions in the same manner as pointers to functions. You can compare pointers to member functions, assign values to them, and use them to call member functions.

How do you call a function from a pointer object?

Using a pointer-to-member-function to call a function Calling the member function on an object using a pointer-to-member-function result = (object. *pointer_name)(arguments); or calling with a pointer to the object result = (object_ptr->*pointer_name)(arguments);

Can you pass a pointer to a function in C?

C programming allows passing a pointer to a function. To do so, simply declare the function parameter as a pointer type.

How can we call member functions through a pointer to an object consider member function is in public section of class?

To access a member function by pointer, we have to declare a pointer to the object and initialize it (by creating the memory at runtime, yes! We can use new keyboard for this). The second step, use arrow operator -> to access the member function using the pointer to the object.


1 Answers

No. A member function is not a free function. The type is entirely different, and a pointer to a member function (PTMF) is a completely different, incompatible object from a function pointer. (A PTMF is usually much bigger, for example.) Most importantly a pointer-to-member must always be used together with an instance pointer to the object whose member you want to call, so you cannot even use a PTMF the same way you use a function pointer.

The easiest solution for interacting with C code is to write a global wrapper function that dispatches your call, or to make your member function static (in which case it becomes essentially a free function):

// global!

Engine * myEngine;
int theCallback(lua_State * L)
{
  return myEngine->pcall_log(L);
}

Engine::Run()
{
  /* ... */
  myEngine = this;
  luabind::set_pcall_callback(&theCallback);
  /* ... */
}

The conceptual problem here is that you have an engine class, although you will practically only have one single instance of it. For a genuine class with many objects, a PTMF wouldn't make sense because you'd have to specify which object to use for the call, whereas your engine class perhaps is essentially a singleton class which could be entirely static (i.e. a glorified namespace).

like image 197
Kerrek SB Avatar answered Sep 27 '22 16:09

Kerrek SB