Передача существующих объектов C ++ в Lua и вызов функций-членов переданных объектов

Я работаю над небольшим симуляционным проектом, который использует Lua для управления поведением отдельных единиц (муравьев) и использую Luabind для склеивания сторон C ++ и Lua вместе. Каждый отдельный муравей (существуют разные типы, производные от базового класса Ant) имеет функцию Run (), которая вызывает соответствующий сценарий; затем сценарий выполняет все действия, которые необходимо предпринять, вызывая функции открытого класса и, возможно, бесплатные функции. У меня есть функция Run (в C ++) для успешного выполнения соответствующей функции Run в сценарии Lua (который в данный момент просто печатает какой-то текст).

void AntQueen::Run()
{
    lua->GetObject("QueenRun")(GetID());
}

lua - это просто класс-менеджер, который извлекает функцию из скрипта. Вышеупомянутое вызывает следующее в файле Lua:

function QueenRun(ID)
    print("The Queen is running!")
    print(ID)
end

А регистрация Luabind для класса AntQueen выглядит так:

void Register(lua_State *luaState)
{
    using namespace luabind;
    module(luaState)
    [
        class_<AntQueen, Ant>("AntQueen")
        .def("Eat", &AntQueen::Eat)
        .def("ExtractLarvae", &AntQueen::ExtractLarvae)
        .def("GetMaxLarvaeProduced", &AntQueen::GetMaxLarvaeProduced)
        .def("GetNumAvailLarvae", &AntQueen::GetNumAvailLarvae)
    ];
}

Как это установлено сейчас, муравьи создаются, удаляются и обнаруживаются с помощью простой фабрики / менеджера. Каждого муравья можно получить, вызвав static Ant* AntFactory::GetAntByID(const int ID), который просто находит муравья в хэш-карте и возвращает указатель на муравья. Я пытаюсь заставить Lua делать что-то вроде следующего:

function QueenRun(ID)
    ant = GetAntByID(ID)
    larvae = ant:GetNumAvailLarvae()
    print(larvae)
    ant:Eat()
end

Вышеупомянутое - всего лишь выдуманный пример, но, надеюсь, он показывает, чего я пытаюсь достичь. Я не хочу, чтобы Lua собирал объекты мусором, потому что они уже управляются на стороне C ++. Пока все проверяем, любая попытка сделать следующее:

ant = GetAntByID(ID)

в Lua приводил к вызову abort(), сбою и сгоранию программы.

R6010
-abort() has been called

Мне просто кажется, что мне чего-то не хватает в том, как все перемещается взад и вперед (это моя первая попытка склеить Lua и C ++ вместе, помимо игрушечных программ). Я почти уверен, что передача простого указателя - не лучший способ; lightuserdata кажется мне тем, что я ищу, но у него также есть ряд ограничений.

Итак, чтобы подвести итог: что здесь происходит, что вызывает вызов abort, и как я могу использовать Luabind / Lua C API, чтобы получить указатель на объект C ++, переданный в Lua, и вызвать функции-члены для этого указателя, как если бы это был объект (не позволяя мусору Lua собирать его)?


person Gemini14    schedule 24.12.2010    source источник
comment
light userdata - это то, что вы хотите использовать. Он предназначен для того, чтобы делать то, что вы хотите, - хранить указатель на данные C в Lua. Это тоже не сборщик мусора.   -  person Łukasz Gruner    schedule 10.01.2011


Ответы (1)


Решение этой проблемы, казалось, было связано с тем, что функции класса / члена AntFactory были статичными. Как только я перестал регистрироваться и пользоваться этим:

//C++

static int AntFactory::CreateAnt(foo, bar)
{}

//Lua

factory:CreateAnt(foo, bar)

к созданному объекту и обычным функциям-членам, например:

//C++

int AntFactory::CreateAnt(foo, bar)
{}

//Lua

factory:CreateAnt(foo, bar)

все работало без проблем (после того, как фабрика была перенесена в глобальную таблицу). Я думаю, что причина этого в том, что попытка вызвать статические функции-члены для не созданного экземпляра объекта C ++ терпит неудачу из-за того, что Lua (или Luabind?) Не может иметь объект для запроса вызовов.

person Gemini14    schedule 11.01.2011