You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取和设置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:02:36