Прежде всего, я прошу прощения за то, что не загружал полный код.
Я пытаюсь конвертировать 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();
}
Я пытаюсь преобразовать userdata в указатель
Не. Это не то же самое, указатель не представляет данные пользователя.
Вы не можете получить объект пользовательских данных Lua через указатель на его область данных.
Если вам нужно манипулировать с пользовательскими данными на собственной стороне, сохраните пользовательские данные в реестре с помощью luaL_ref()
и используйте возвращенное целое число в качестве ссылки. Позже вы можете извлечь этот объект из реестра и получить указатель на его область данных, когда вам нужно. Но не храните только указатель.
Что касается проблемы со ссылочной таблицей, объект, который будет сохранен в реестре с luaL_ref()
должно быть на вершине стека Lua. Но сейчас единственной вещью, которая остается на вершине стека Lua, является стол. Вы копируете значение этой таблицы для повторения с while(lua_next())
и все, что читается из таблицы в этом цикле, извлекается из стека в конце цикла.
Вероятно, вы не должны даже строить av
структурировать и обрабатывать данные сразу же при сканировании исходной таблицы. Вам не нужно повторно или повторно ссылаться на userdata.
Если вы действительно должны иметь это av
затем вместо указателя на память пользовательских данных сохраните целочисленный индекс, возвращаемый luaL_ref()
, И вы должны сделать это в первом цикле, а не во втором. Второй цикл тогда будет делать lua_rawgeti()
получить объект userdata, и после обработки вы можете отменить его.
Других решений пока нет …