如何获取和设置Lua的lightuserdata:存指针到lua_State并回调读取
用原生Lua API实现指针存储与取回
要在Lua全局环境(所有回调共享)里存lightuserdata,最安全的方式是用Lua的注册表(registry)——这是Lua专门给C扩展用的全局表,不会和用户代码里的变量冲突。
完整实现代码:
#include <lua.h> #include <lauxlib.h> // 定义唯一的注册表键,避免和其他数据冲突 #define GLOBAL_POINTER_KEY "app_global_pointer" void SetPointer(lua_State* L, void* p) { lua_pushlightuserdata(L, p); // 将栈顶的lightuserdata存入注册表,关联到自定义键 lua_setfield(L, LUA_REGISTRYINDEX, GLOBAL_POINTER_KEY); } void* GetPointer(lua_State* L) { // 从注册表取出对应键的lightuserdata lua_getfield(L, LUA_REGISTRYINDEX, GLOBAL_POINTER_KEY); // 把栈顶的lightuserdata转成C指针 void* p = lua_touserdata(L, -1); // 取出后弹出栈顶元素,防止栈溢出 lua_pop(L, 1); return p; }
关键说明:
LUA_REGISTRYINDEX是Lua注册表在栈上的伪索引,直接用它操作注册表- 必须用唯一的键(比如自定义字符串),避免和其他C扩展的数据冲突
- 取指针后记得
lua_pop清理栈,否则后续栈操作会出错
用Sol2库实现指针存储与取回
Sol2封装了Lua API,操作更简洁,同样推荐用注册表存全局指针:
基于sol::state的实现:
#include <sol/sol.hpp> void SetPointer(sol::state& lua, void* p) { // sol::reg代表Lua注册表,直接存入lightuserdata lua[sol::reg]["app_global_pointer"] = sol::light_userdata(p); } void* GetPointer(sol::state& lua) { // 从注册表取出并转换为C指针 sol::light_userdata lu_ptr = lua[sol::reg]["app_global_pointer"]; return lu_ptr.value(); }
直接用lua_State*的实现:
如果已经有现成的lua_State*,用sol::state_view即可,不需要创建新的sol::state对象:
#include <sol/sol.hpp> void SetPointer(lua_State* L, void* p) { sol::state_view lua(L); lua[sol::reg]["app_global_pointer"] = sol::light_userdata(p); } void* GetPointer(lua_State* L) { sol::state_view lua(L); sol::light_userdata lu_ptr = lua[sol::reg]["app_global_pointer"]; return lu_ptr.value(); }
关键说明:
sol::light_userdata直接对应Lua的lightuserdata类型,安全包装C指针sol::reg是Sol2提供的注册表访问入口,用法和原生API一致但更直观
内容的提问来源于stack exchange,提问作者Dess
相关产品推荐
相关产品推荐

