我目前正在使用 GCC 4.4,并且在 void*
和指向成员函数的指针之间进行转换非常头疼。我正在尝试编写一个易于使用的库,用于将 C++ 对象绑定到 Lua 解释器,如下所示:
LuaObject<Foo> lobj = registerObject(L, "foo", fooObject);
lobj.addField(L, "bar", &Foo::bar);
我已经完成了大部分工作,除了以下函数(在我有机会概括它之前,它是特定于某个函数签名的):
template <class T>
int call_int_function(lua_State *L)
{
// this next line is problematic
void (T::*method)(int, int) = reinterpret_cast<void (T::*)(int, int)>(lua_touserdata(L, lua_upvalueindex(1)));
T *obj = reinterpret_cast<T *>(lua_touserdata(L, 1));
(obj->*method)(lua_tointeger(L, 2), lua_tointeger(L, 3));
return 0;
}
对于那些不熟悉 Lua 的人, lua_touserdata(L, lua_upvalueindex(1))
获取与闭包关联的第一个值(在本例中,它是指向成员函数的指针)并将其作为 void*
返回。 GCC 抱怨 void*
-> void (T::*)(int, int)
是无效演员表。关于如何解决这个问题的任何想法?
原文由 Rob Hoelz 发布,翻译遵循 CC BY-SA 4.0 许可协议
您 不能将指向成员的指针强制转换为
void *
或任何其他“常规”指针类型。指向成员的指针不是像常规指针那样的地址。您最可能需要做的是将您的成员函数包装在常规函数中。 C++ FAQ Lite 详细解释了这一点。主要问题是实现指向成员的指针所需的数据不仅仅是一个地址,实际上根据编译器的实现 变化很大。我认为您可以控制用户数据
lua_touserdata
返回的内容。它不能是指向成员的指针,因为没有合法的方式来获取此信息。但是您确实有其他一些选择:最简单的选择可能是将您的成员函数包装在一个自由函数中并返回它。该自由函数应将对象作为其第一个参数。请参阅下面的代码示例。
使用类似于 Boost.Bind 的 mem_fun 的技术来返回一个函数对象,您可以在该对象上进行适当的模板化。我不认为这更容易,但是如果需要,它可以让您将更多状态与函数返回相关联。
这是使用第一种方式重写您的函数: