Прежде всего, я прошу прощения за то, что не загрузил полный код.
Я пытаюсь преобразовать userdata
в pointer
, чтобы он мог быть передан другому lua чанку с помощью lua_rawgeti()
.
Если вы видите функцию outletRet()
, она проверяет тип возвращаемого значения, а если это userdata
, она передает указатель на другой кусок lua, вызывая outlet_pointer()
, и, похоже, работает нормально.
И если 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();
}