在 void * 和指向成员函数的指针之间转换。
我目前正在使用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)
是无效的转换。有什么想法可以解决这个问题吗?
原文链接 https://stackoverflow.com/questions/1307278
由于将成员函数指针转换为 void*
的限制,您可以将函数指针包装在一个小的堆分配结构中,并将一个指向该结构的指针放入 Lua 用户数据中,以解决此问题:
template <typename T>
struct LuaUserData {
typename void (T::*MemberProc)(int, int);
explicit LuaUserData(MemberProc proc) :
mProc(proc)
{ }
MemberProc mProc;
};
LuaObject<Foo> lobj = registerObject(L, "foo", fooObject);
LuaUserData<Foo>* lobj_data = new LuaUserData<Foo>(&Foo::bar);
lobj.addField(L, "bar", lobj_data);
// ...
template <class T>
int call_int_function(lua_State *L)
{
typedef LuaUserData<T> LuaUserDataType;
typedef typename LuaUserDataType::MemberProc ProcType;
// this next line is problematic
LuaUserDataType* data =
reinterpret_cast<LuaUserDataType*>(lua_touserdata(L, lua_upvalueindex(1)));
T *obj = reinterpret_cast<T *>(lua_touserdata(L, 1));
(obj->*(data.mMemberProc))(lua_tointeger(L, 2), lua_tointeger(L, 3));
return 0;
}
我不熟悉 Lua,因此我可能会忽略上述示例中的某些内容。请记住,如果您选择这种方法,您将需要管理 LuaUserData 的分配。
可以使用 union 将成员函数和属性指针进行转换:
// 帮助转换成员指针的 union
template<typename classT, typename memberT>
union u_ptm_cast {
memberT classT::*pmember;
void *pvoid;
};
要进行转换,将源值放入一个成员中,然后从另一个成员中取出目标值。
虽然这种方法很实用,但我不知道它是否在每种情况下都能正常工作。
与 非静态 成员函数的地址不同,后者是一种具有复杂表示的成员指针类型,静态成员函数的地址通常只是一个可转换为 void*
的机器地址。
如果您需要将 C++ 的非静态成员函数绑定到基于 void*
的 C 或类 C 回调机制上,您可以尝试编写一个静态包装器。
该包装器可以将实例指针作为参数,并将控制权传递给非静态成员函数:
void myclass::static_fun(myclass *instance, int arge
{
instance->nonstatic_fun(arg);
}
下面是代码的中文翻译,且保留原本的 markdown 格式:
在这里,只需更改函数 void_cast 的参数以使其适应您的需求:
template<typename T, typename R>
void* void_cast(R(T::*f)())
{
union
{
R(T::*pf)();
void* p;
};
pf = f;
return p;
}
使用示例:
auto pvoid = void_cast(&Foo::foo);
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
你不能将指向成员的指针转换为
void *
,也不能转换为其他“常规”指针类型。指向成员的指针不像常规指针一样是地址。你最有可能需要做的是将成员函数包装在一个常规函数中。C++ FAQ Lite 对此进行了详细的解释。主要问题是实现指向成员指针所需的数据不仅仅是一个地址,并且实际上根据编译器的实现方式变化很大。我假设你对用户数据
lua_touserdata
返回有控制权。它不能是一个指向成员的指针,因为没有合法的方法来取回这个信息。但你确实有其他选择:这是使用第一种方法重新编写您的函数的方式:
template <class T> int call_int_function(lua_State *L) { void (*method)(T*, int, int) = reinterpret_cast<void (*)(T*, int, int)>(lua_touserdata(L, lua_upvalueindex(1))); T *obj = reinterpret_cast<T *>(lua_touserdata(L, 1)); method(obj, lua_tointeger(L, 2), lua_tointeger(L, 3)); return 0; }