Lua userdata变量与c++的通信
Lua userdata variable communication with C++
我有一个程序,用户可以使用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;
}
由于帧是显示给用户的,因此用户只需点击操作系统提供的关闭按钮即可关闭该帧。这会生成一个close事件,处理方法如下:
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
完全不同的地址,因此我不知道我引用的是哪个类型的frame变量。
根据我的理解,wb2
可能由于3种情况而具有不同的内存地址:
1) frm
是完整的userdata
2) from在全局lua表中,因此有一个不同的地址(尽管这对我来说没有意义,因为我在c++中推送了Frame的地址)。
我的思路完全错了,或者我看不清一些简单的东西。
现在我的理解是,我需要做的是搜索全局表的userdata类型帧和比较内存地址,以便我知道我选择了正确的帧,然后将其设置为nil。
你的理解是错误的。
首先,您没有向Lua返回userdata。您返回light userdata。这是不同的。轻userdata的lua_type
为LUA_TLIGHTUSERDATA
。
global_var = {}
global_var.frame = Frame.new()
Lua代码应该能够在任何它想要的地方存储它的数据。如果它想在表中存储一些用户数据,你又有什么资格说不呢?
第三,即使你递归地遍历全局可访问的所有表(有无限循环保护),也不会阻止:local frm = Frame.new()
function GlobalFunc(...)
frm:Stuff();
end
由于Lua具有适当的词法作用域,GlobalFunc
将在内部
frm
本地的引用。因为frm
是一个local
变量,你不能仅仅通过迭代全局变量来得到它。
一般来说,如果你给Lua一个值,它现在拥有这个值。它可以做任何它想做的事,通常认为破坏这个契约是不礼貌的。
虽然不是不可能。处理它的方法是使用实际的 userdata,而不是轻userdata。每个常规userdata都是一个对象,一个完整的内存分配。在这个分配中,您将存储Frame
指针。当需要销毁Frame
时,您所要做的就是将userdata内部的Frame
指针设置为NULL。
struct FramePtr
{
Frame *ptr;
};
Lua将传递单个FramePtr
分配。如果你设置那个分配的FramePtr
为NULL,每个人都能看到它。没有遍历全局表之类的
当然,从FramePtr
访问Frame
需要额外的间接。然而,通过使用完整userdata而不是轻量级userdata,你也可以为它附加一个适当的元表(轻量级userdata不获得每个对象的元表;
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 是否可以使用winusb同时与多个相同的usb设备进行通信
- 混淆了如何使用IDL与Ethovision进行通信
- C++ Boost::asio串行通信与Arduino无法写入
- 我是否需要包含隐式使用/与 WindowsAPI 通信"Windows.h"?
- 通过TCP的PvP通信问题
- C++一个线程如何正确通信其任务已完成?
- 如何将 Firebase 与基于 Linux 的客户端应用配合使用,以便与服务器进行双向消息通信
- 删除功能不适用于串行通信后多个循环中的多个实例
- 网站和C++程序在同一台 Linux PC 上的通信
- 通过插槽和信号在不同线程中的两个qt对象之间进行通信
- 使用 pybind11 共享 MPI 通信器
- 进程间通信堆内存
- C++ TCP 套接字通信 - 连接按预期工作,几秒钟后失败,没有收到新数据,read() 和 recv() 块
- C++ 两台不同机器之间通过wifi进行套接字通信
- 提升::Asio 异步聊天客户端停止与服务器通信
- 与SPI NAND闪存(STM32L4,QSPI)的通信问题
- 线程之间的通信不起作用 - C++
- 如何在此功能中没有通信过程?
- MPI 集合通信中的指针分配