首先,我对没有上传完整的代码表示歉意。
我正在尝试将userdata
转换为pointer
,以便可以使用lua_rawgeti()
将其传递给其他lua块。
如果看到outletRet()
函数,它将检查返回值的类型,如果它是userdata
,则通过调用outlet_pointer()
将指针传递给其他lua块,这似乎工作正常。
如果userdata
在table
内部,则调用outletTable()
函数。而且,如果其元素之一是userdata
,它还将userdata
转换为pointer
,然后通过调用outlet_pointer()
将其传递给其他块。
但是,当调用luaL_ref(L, LUA_REGISTRYINDEX)
时,似乎它引用了整个table
,而不仅仅是其中的userdata
。
如何获取对userdata
而不是整个table
的引用?
void ofLua::outletTable() //called from outletRet() below
{
lua_pushvalue(L, -1);
lua_pushnil(L);
int ac = 0;
t_atom *av = static_cast<t_atom *>(getbytes(sizeof(t_atom) * ac));
while (lua_next(L, -2))
{
av = static_cast<t_atom *>(resizebytes(av, sizeof(t_atom) * ac,
sizeof(t_atom) * (ac + 1)));
if (lua_isboolean(L, -1))
{
av[ac].a_type = A_FLOAT;
av[ac].a_w.w_float = static_cast<t_float>(lua_toboolean(L, -1));
}
else if (lua_isnumber(L, -1))
{
av[ac].a_type = A_FLOAT;
av[ac].a_w.w_float = static_cast<t_float>(lua_tonumber(L, -1));
}
else if (lua_isstring(L, -1))
{
av[ac].a_type = A_SYMBOL;
av[ac].a_w.w_symbol = gensym(lua_tostring(L, -1));
}
else if (lua_isuserdata(L, -1))
{
av[ac].a_type = A_POINTER;
}
ac++;
lua_pop(L, 1);
}
lua_pop(L, 1);
const ofeliaIO &io = dataPtr->io;
if (io.hasMultiControlOutlets)
{
int last = (io.numOutlets >= ac ? ac : io.numOutlets) - 1;
for (int i = last; i >= 0; --i)
{
if (av[i].a_type == A_FLOAT)
outlet_float(io.outlets[i], av[i].a_w.w_float);
else if (av[i].a_type == A_SYMBOL)
outlet_symbol(io.outlets[i], av[i].a_w.w_symbol);
else if (av[i].a_type == A_POINTER)
{
userDataRefVec.push_back(luaL_ref(L, LUA_REGISTRYINDEX));
outlet_pointer(io.outlets[i], reinterpret_cast<t_gpointer *>(&userDataRefVec.back()));
luaL_unref(L, LUA_REGISTRYINDEX, userDataRefVec.back());
userDataRefVec.pop_back();
}
}
}
else
outlet_list(dataPtr->ob.ob_outlet, &s_list, ac, av);
freebytes(av, sizeof(t_atom) * ac);
}
void ofLua::outletRet()
{
const ofeliaIO &io = dataPtr->io;
if (!io.hasControlOutlet) return;
if (lua_isnil(L, -1))
outlet_bang(io.outlets[0]);
else if (lua_isboolean(L, -1))
outlet_float(io.outlets[0], static_cast<t_float>(lua_toboolean(L, -1)));
else if (lua_isnumber(L, -1))
outlet_float(io.outlets[0], static_cast<t_float>(lua_tonumber(L, -1)));
else if (lua_isstring(L, -1))
outlet_symbol(io.outlets[0], gensym(lua_tostring(L, -1)));
else if (lua_isuserdata(L, -1))
{
userDataRefVec.push_back(luaL_ref(L, LUA_REGISTRYINDEX));
outlet_pointer(io.outlets[0], reinterpret_cast<t_gpointer *>(&userDataRefVec.back()));
luaL_unref(L, LUA_REGISTRYINDEX, userDataRefVec.back());
userDataRefVec.pop_back();
}
else if (lua_istable(L, -1))
outletTable();
}
答案 0 :(得分:2)
我正在尝试将用户数据转换为指针
不要。不一样,指针不代表用户数据。 您不能通过指向其数据区域的指针来检索Lua userdata对象。
如果需要在本机端使用userdata进行操作,请使用luaL_ref()
将userdata保存在注册表中,并使用返回的整数作为参考。以后,您可以从注册表中检索该对象,并在需要时获取指向其数据区域的指针。但是不要只存储指针。
对于引用表的问题,要用luaL_ref()
保存在注册表中的对象必须在Lua堆栈顶部。但是现在,唯一留在Lua堆栈顶部的是桌子。复制该表的值以使用while(lua_next())
进行迭代,然后在该循环结束时从堆栈中弹出从该循环中的表读取的所有内容。
可能您甚至根本不需要构建av
结构,并且在扫描原始表时立即处理数据。然后,您不需要引用/取消引用用户数据。
如果确实必须具有该av
,请保存luaL_ref()
返回的整数索引,而不是指向userdata内存的指针。您应该在第一个循环中执行此操作,而不是在第二个循环中执行。然后,第二个循环将执行lua_rawgeti()
以获取userdata对象,并且在处理之后可以取消引用。