【发布时间】:2016-08-23 10:56:37
【问题描述】:
我有一个程序,用户可以使用 Lua 命令创建框架,例如:
frm=Frame.new()
上述命令向用户显示一个框架。幕后的 C++ 封装如下:
Frame* Frame_new(lua_State* L)
{
int nargs=lua_gettop(L);
Frame* wb=0;
if(nargs==0){
//Omitted
wb=mainfrm->GetFrame();
lua_pushlightuserdata(L,(void*)(wb));
int key=luaL_ref(L, LUA_REGISTRYINDEX);
wb->SetLuaRegistryKey(key);
}
return wb;
}
由于向用户显示了框架,用户只需单击操作系统提供的关闭按钮即可关闭框架。这会产生一个关闭事件,它的处理方式如下:
void Frm::OnClose(wxCloseEvent& evt)
{
//Omitted for brevity
int LuaRegistryKey=GetFrame()->GetLuaRegistryKey();
lua_rawgeti(glbLuaState,LUA_REGISTRYINDEX,LuaRegistryKey);//userdata
Frame* wb1=(Frame*)lua_touserdata(glbLuaState,-1); //userdata
lua_pop(glbLuaState,1); //
lua_getglobal(glbLuaState,"_G"); //table
lua_pushnil(glbLuaState); //table key
while (lua_next(glbLuaState,-2)) {//table key value
const char* name = lua_tostring(glbLuaState,-2);//table
if(lua_type(glbLuaState,-1)==LUA_TUSERDATA){
Frame* wb2=(Frame*)lua_touserdata(glbLuaState,-1);
if(wb2==m_Frame){ //this part doesnt work
lua_pushnumber(glbLuaState,0);
lua_setglobal(glbLuaState,name);
lua_pop(glbLuaState,1);
break;
}
}
lua_pop(glbLuaState,1); //table key
} //table
lua_pop(glbLuaState,1); //
if(m_Frame==wb1) {delete m_Frame; m_Frame=0; wb1=0;}
if(wb1) {delete wb1; wb1=0;}
luaL_unref(glbLuaState,LUA_REGISTRYINDEX,LuaRegistryKey );
}
现在的目标是当用户关闭框架时,frm=Frame.new() 创建的变量应该为 nil,这样用户就不能调用它的方法之一,例如导致程序崩溃的 frm:size()。
在上述处理关闭事件的 C++ 代码中,wb1 和当前帧具有相同的内存地址。 现在据我所知我需要做的就是在全局表中搜索用户数据类型Frame 并比较内存地址,以便我知道我选择了正确的帧,然后将其设置为 nil。
但是,Frame* wb2=(Frame*)lua_touserdata(glbLuaState,-1); 返回与wb1 完全不同的地址,因此我不知道我指的是哪个类型的框架变量。
据我了解,wb2 有不同的内存地址可能是由于 3 种情况:
1) frm 是完整的用户数据
2) frm 在全局 lua 表中,因此具有不同的地址(尽管这对我来说没有意义,因为我在 C++ 中推送了 Frame 的地址)。
3) 我的思维方式完全错误,或者看不到简单的东西。
【问题讨论】: