Передать объект C ++ функции Lua - PullRequest
7 голосов
/ 06 апреля 2010

У меня есть проект на C ++, где 1 метод 1 класса меняется очень часто. Поэтому я хочу перенести этот код из C ++ в Lua. Обратите внимание, я новичок в Луа.

Вся задача:

  1. Привязать некоторые методы класса к конечному автомату Lua;
  2. Передать ссылку на объект класса в функцию, написанную на Lua;
  3. Работа с переданным объектом C ++ в функции Lua.

Я нашел, как сделать первый шаг с Лунным, и не могу справиться со вторым и третьим.

Я не могу использовать SWIG и Boost.

Ответы [ 3 ]

8 голосов
/ 06 апреля 2010
//This has a large number of steps, but I'm gonna post them all. This is all using native Lua 5 and the lua CAPI.
int CreateInstanceOfT(lua_State* L) {
    new (lua_newuserdata(L, sizeof(T))) T(constructor args);
    return 1;
}
int CallSomeFuncOnT(lua_State* L) {
    if (lua_istable(L, 1)) { // If we're passed a table, get CData
        lua_getfield(L, 1, "CData");
        lua_replace(L, 1);
    }
    if (!lua_touserdata(L, 1))
        lua_error(L); // longjmp out.
    T& ref = *(T*)lua_touserdata(L, 1);
    ref.SomeFunc(); // If you want args, I'll assume that you can pass them yourself
    return 0;
}
int main() {
    lua_State* L = luaL_newstate();
    lua_pushcfunction(L, CreateInstanceOfT);
    lua_setglobal(L, "CreateInstanceOfT");
    lua_pushcfunction(L, CallSomeFuncOnT);
    lua_setglobal(L, "CallSomeFuncOnT");
    luaL_dofile(L, "something.lua");
    lua_close(L);
}
-- Accompanying Lua code: semicolons are optional but I do out of habit. In something.lua
function CreateCInstance()
    local Instance = {
        CData = CreateInstanceOfT();
        SomeFunc = CallSomeFuncOnT;
    }
    return Instance;
end

local object = CreateCInstance();
object:SomeFunc(); // Calls somefunc.

Я мог бы опубликовать огромное количество подробностей о том, как сделать экспозицию проще, как сделать наследование и тому подобное - и это нужно будет изменить, если вы хотите выставить более одного T (я думаю, что наиболееобщее решение - простая struct { std::auto_ptr<void>, int type } сделка).Но это должно быть отправной точкой, если вы ничего не понимаете в этом процессе.

Вначале мы просим Lua выделить некоторое пространство (userdata), а затем вставить в него T.Когда вызывается CallSomeFuncOnT, сначала мы спрашиваем, есть ли у нас таблица (многие классы Lua основаны на таблицах, поскольку они поддерживают ориентацию объектов, метатаблицы и т. Д.), И выводим пользовательские данные, которые мы затем преобразуем в указатель на нашобъект, а затем преобразовать в ссылку.Помните, что lua_touserdata дает вам пустоту *, так что вам лучше быть чертовски уверенным в том, что находится на другом конце.Затем мы вызываем somefunc и возвращаемся.В Main мы просто регистрируем функции как глобальные.

Теперь, в Lua, когда вы вызываете CreateInstanceOfT, он фактически просто вызывает конструктор T, прозрачно для пользователя Lua.Затем мы бросаем его в таблицу, что проще для новичков Lua, и вызываем SomeFunc, передавая эту таблицу.

1 голос
/ 06 апреля 2010

Как и Джон, я использовал luabind и рекомендую его. Однако, так как использование boost для вас не вариант, список библиотек на этой странице может оказаться полезным. Вы также можете проверить страницу DoItYourselfCppBinding на вики lua-users .

Одна библиотека, упомянутая на странице, это oolua , которая не имеет зависимостей (как говорится).

1 голос
/ 06 апреля 2010

Вы смотрели на luabind ? Это позволяет довольно легко выставлять объекты и функции C ++ в LUA.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...