C++类成员函数指针到函数指针

2021-12-31 00:00:00 function-pointers casting c++ luabind

我使用 luabind 作为我的 lua 到 C++ 包装器.Luabind 提供了一种方法来使用我自己的回调函数来处理lua 抛出的异常,set_pcall_callback().所以我解释了文档中的一个例子,变化是 logger->log() 函数并将该函数放在一个名为Engine"的类中,所以它不是一个常规的全局函数,它现在是一个成员函数,它是我的问题似乎在哪里.

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:pbengine.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*))'|

所以看起来这个错误是函数需要一个普通的函数指针,而不是一个类成员函数指针.有没有办法强制转换或使用中间函数指针传递给 set_pcall_callback() 函数?

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?

谢谢!

推荐答案

没有.成员函数不是自由函数.类型完全不同,指向成员函数的指针 (PTMF) 是与函数指针完全不同的、不兼容的对象.(例如,PTMF 通常要大得多.)最重要的是,指向成员的指针必须始终与指向要调用其成员的对象的实例指针一起使用,因此您甚至不能使用 PTMF 与使用函数指针的方式相同.

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.

与 C 代码交互的最简单的解决方案是编写一个全局包装函数来调度您的调用,或者使您的成员函数静态(在这种情况下,它本质上变成了一个自由函数):

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);
  /* ... */
}

这里的概念问题是你有一个引擎类,尽管你实际上只有一个它的实例.对于具有许多对象的真正类,PTMF 没有意义,因为您必须指定要用于调用的对象,而您的引擎类可能本质上是一个可以完全静态的单例类(即美化的命名空间).

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).

相关文章