保存对Lua用户数据的引用
2018-7-14 17:3:24
收藏:0
阅读:288
评论:2
#1 Lua:
local test = Test();
本地变量test
赋值为Test()
函数的返回值。
#2 C:
//creating "lua's test"
luaL_newmetatable(L, "someTable");
lua_userdata *userData = (lua_userdata *)lua_newuserdata(L, sizeof(lua_userdata));
luaL_getmetatable(L, "someTable");
lua_setmetatable(L, -2);
创建元表“someTable
”,并创建名为lua_userdata
的userdata
。获得元表“someTable
”,为userdata
设置元表。
#3 Lua:
function test.newMethod()
end
添加test
对象的newMethod()
方法。
#4 C:
//this part is not executed from Lua
//what i have to have here from #2 to call "test.newMethod" and how to call it?
//if userdata would be on stack i guess i could:
luaL_getmetafield (L, 1, "newMethod");
lua_call(L, 0, 0);
//but because this part is not executed by Lua call its not on stack.
这部分代码没有被Lua执行,所以没有userdata
在栈上。如果userdata
在栈上,可以用luaL_getmetafield(L, 1, "newMethod")
获得newMethod()
方法,并用lua_call(L, 0, 0)
调用它。
编辑:
试着用伪代码更简单地解释:
Lua:
local test = Object();
C:
int Object(){
...
somePointer = luaL_newmetatable(...); //如何得到“somePointer”? 可以用luaL_ref()吗?
push ...
}
Lua: 创建新的方法
function test.newMethod()
...
end
C:某个事件(比如计时器)触发C方法
void triggeredCMethod(){
//这里我需要调用test.newMethod方法
//如果我能得到 'somePointer' 并将其推到Lua栈上,我就能查找并调用newMethod()
}
所以问题是:如何在C中存储指向某个Lua对象的指针(希望我需要这个),如何通过该指针获得Lua对象并调用其中的方法。
原文链接 https://stackoverflow.com/questions/1646497
点赞
stackoverflow用户197131
我假设您想要能够调用动态添加的函数。这段代码应该相对简单地解释了它。请注意,我没有做太多的错误检查并做了一些假设,不要将它复制粘贴为解决方案。
typedef struct
{
int number;
int reference;
lua_State *L;
} TestUserdata;
static int m_newindex( lua_State *L )
{
/* 这个函数会传递三个值,第一个(-3)是对象,将其放到最前面*/
lua_getfenv( L, -3 );
/* 现在将第二个参数(即key)向前传输*/
lua_pushvalue( L, -3 );
/* 还有第三个参数(即value)*/
lua_pushvalue( L, -3 );
/* 然后我们就完成了*/
lua_rawset( L, -3 );
return 0;
}
static int m_tostring( lua_State *L )
{
lua_pushstring( L, "TestUserdata" );
return 1;
}
static int callobject( lua_State *L )
{
/* 抓住传入的对象,检查它是否是正确的类型*/
TestUserdata *data = luaL_checkudata( L, 1, "TestUserdata" );
/* 获取我们在createobject中给它的函数环境,并在其中查找newmethod*/
lua_getfenv( L, -1 );
lua_pushstring( L, "newmethod" );
lua_rawget( L, -2 );
/* 调用函数*/
lua_pushinteger( L, data->number );
lua_call( L, 1, 0 );
return 0;
}
static const struct luaL_reg userdata_m[] = {
{ "__newindex", m_newindex },
{ "__tostring", m_tostring },
{ NULL, NULL }
};
int main (int argc, char *argv[])
{
lua_State *L = luaL_newstate();
luaL_openlibs( L );
/* 让我们创建一个用户数据元表,并将其填充*/
luaL_newmetatable( L, "TestUserdata" );
/* 使用luaL_register为我们填充元表*/
luaL_register( L, NULL, userdata_m );
lua_pop( L, 1 ); /* 清理堆栈,我们不需要在这里留下元表*/
TestUserdata *data = lua_newuserdata( L, sizeof( TestUserdata ) );
lua_pushvalue( L, -1 ); /* 复制用于luaL_ref*/
int ref = luaL_ref( L, LUA_REGISTRYINDEX );
data->reference = ref;
data->number = 42;
data->L = L;
/*从之前的元表中加载并给这个用户数据*/
luaL_getmetatable( L, "TestUserdata" );
lua_setmetatable( L, -2 );
/*为这个对象提供空的函数环境*/
lua_newtable( L );
lua_setfenv( L, -2 );
lua_setglobal( L, "test" );
luaL_dostring( L, "function test.newmethod( num ) print( num ) end" );
/* 现在只要有对象,就可以调用任何在任何地方定义过的方法*/
lua_rawgeti( data->L, LUA_REGISTRYINDEX, data->reference );
lua_getfenv( data->L, -1 );
lua_pushstring( data->L, "newmethod" );
lua_rawget( data->L, -2 );
lua_remove( data->L, -2 );
if( lua_isfunction( data->L, -1 ) == 1 )
{
lua_pushinteger( data->L, data->number );
lua_pcall( data->L, 1, 0, 0 );
}
lua_close( L );
return 0;
}
请检查一下,我认为这就是您要的内容。
2009-10-30 06:25:02
评论区的留言会收到邮件通知哦~
推荐文章
- 如何在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 模式将字符串(嵌套数组)转换为真正的数组?
如果你只是想调用 Lua 函数 `test.newMethod()',我认为你需要大致使用这样的方式:
lua_getglobal(L, "test"); lua_getfield(L, -1, "newMethod"); lua_call(L, 0, 0);
我不认为你需要使用元表或用户数据来实现。
然而,你问题的意图并不是完全清楚的。