Вопрос по lua – Песочница Embedded Lua в 5.2 / Установить среду для функций из lua.file

7

Допустим, у меня есть как минимум два файла сценария lua.

test1.lua test2.lua

оба определяют функцию инициализации и другие функции с похожими именами.

Как я могу загрузить каждый файл скрипта, используя c ++ / c, в отдельную среду, использующую Lua 5.2, чтобы те же имена функций не конфликтовали - я нашел пример кода для 5.1, который у меня не работает (потому что setenv пропал, а lua_setuservalue не работает похоже на работу)

Образец здесьВызов функций lua из .lua с помощью ручек?

В основном, если я заменяю setenv на setuservalue - я получаю нарушение прав доступа.

спасибо - я посмотрел в upvalues - и нашел этот пост в спискеlua-list.2524044.n2.nabble.com/… в основном сказано, что вы должны вызывать if (luaL_loadfile (L, filename)) return lua_error (L); lua_getglobal (L, "environment); lua_setupvalue (L, -2, 1); lua_call (L, 0, 0); однако - когда я делаю это, я получаю ошибку «PANIC: незащищенная ошибка при вызове Lua API (test1.lua: 1: попытка индексировать upvaue» _ENV »(нулевое значение))» Steve
спасибо, но я прочитал о загрузке и загрузке файла, однако я не мог найти решение Steve
Я бы с подозрением относился к людям, предлагающим вам позвонитьlua_setupvalue, Он находится в документации как часть API отладки, и поэтому вам не нужно прикасаться к нему для нормального использования lua. Rook
setuservalue это определенно не правильная функция для использования при манипулировании средой. Тем не менее, в документах lua не совсем ясно, что вам следует делать.lua_load говорит, что в качестве его среды задано одно значение, связанное с загруженным чанком, но не упоминает, как вы собираетесь связать значение с чанком из C. Если вы загружали чанк из lua, версия luaload функция выглядит так, как будто должна правильно устанавливать среду. Rook
Это одна из причин, по которой я сейчас остановился на lua 5.1 в своих собственных проектах. Я считаю, что v5.2load а такжеloadfile функции позволяют указать среду; они, вероятно, являются лучшим местом для начала поиска решения. Rook

Ваш Ответ

2   ответа
8

неофициальный FAQ по Lua Я предполагаю, что вы можете достаточно легко перенести эту логику в ваш код C / C ++.

Смотрите такжеLuaFiveTo на вики-сайте lua-users.

Correction

Это действительно не так тривиально, как казалось. Но в конце концов все просто: загрузите свой чанк, нажмите на таблицу _ENV, используйтеlua_setupvalue(L,-2,1), Важно то, что таблица должна быть на вершине стека.

В качестве небольшого примера, используя 2 среды по умолчанию _G для чтения содержимого через метатаблицы:

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

int main(void){
        lua_State *L = luaL_newstate();
        char *file1 = "file1.lua";
        char *file2 = "file2.lua";

        luaL_openlibs(L);

        luaL_loadfile(L,file2); // S: 1
        luaL_loadfile(L,file1); // S: 2
        lua_newtable(L); // ENV for file 1: S: 321
        lua_newtable(L); // ENV for file 2: S: 4321

        //lets have each function have its metatable, where missed lookups are
        //instead looked up in the global table _G

        lua_newtable(L); // metatable S: 54321
        lua_getglobal(L,"_G"); // pushes _G, which will be the __index metatable entry S: 654321

        lua_setfield(L,-2,"__index"); // metatable on top S: 54321
        lua_pushvalue(L,-1); // copy the metatable S: 554321
        lua_setmetatable(L,-3); // set the last copy for env2 S: 54321
        lua_setmetatable(L,-3); // set the original for env1  S: 4321
        // here we end up having 2 tables on the stack for 2 environments
        lua_setupvalue(L,1,1); // first upvalue == _ENV so set it. S: 321
        lua_setupvalue(L,2,1); // set _ENV for file S: 21
        // Remaining on the stack: 2 chunks with env set.
        lua_pcall(L,0,LUA_MULTRET,0);
        lua_pcall(L,0,LUA_MULTRET,0);
        lua_close(L);
        return 0;
}

И для 2 файлов Lua:

-- file1.lua
function init()
        A="foo"
        print("Hello from file1")
        print(A)
end
init()

-- file2.lua
-- this shows that stuff defined in file1 will not polute the environment for file2
print("init function is",tostring(init))
function init()
        A="bar"
        print("Hello from file2")
        print(A)
end
init()
спасибо, но я знаю эти ресурсы - однако я не могу воспроизвести это на C / C ++ Steve
Действительно, проблема в том, что C эквивалентыload а такжеloadfile не имеют такого простого интерфейса или документации. Вики-страница lua-users также выглядит немного устаревшей и содержит функции, которые никогда не входили в спецификацию 5.2.
jpjacobs, мы встретились сегодня в lua-irc и, как я уже сказал, я нашел решение, но еще раз спасибо за пример альтернативного примера! Steve
0

Прежде всего, почему эти функцииglobal? Они должны быть локальными для сценария. Если вы собираетесьrequire их в других файлах, они должны создать и вернуть таблицу, содержащую функции, которые они хотят представить.

Современная идиома, когда требуются эти файлы, заключается в следующем:

local Library = require 'library'

Library.Func1(...)

Таким образом, вы не загрязняете глобальное пространство имен Lua. Вы используете локальные переменные.

Однако, если вы настаиваете на использовании глобальных переменных, подобных этому, вы можете сделать именно то, что сказано в документации: изменить первое значение скомпилированного фрагмента.

Basically if i replace setenv with setuservalue - i get an access violation.

Конечно, у вас. Это не то, чтоlua_setuservalue does, Он предназначен для установки значений, связанных сuserdata, То, что вы хотите, соответственно называетсяlua_setupvalue.

Используя приведенный вами пример кода, правильный ответ будет следующим:

lua_setupvalue(L, -2, 1);
я сам разобрался - lua_setupvalue (L, -2, 0); вылетает! - мне сошло с рук использование lua_setupvalue (L, -2, 1); - мои знания ограничены, и я точно знаю, что я в этом контексте. но это похоже на работу - теперь возможно также выставить мой объект только в этом «пространстве имен» а не в глобальной таблице? я использую luabind для показа своих классов и в настоящее время использую luabind :: globals (myLuaState) [& quot; myObj & quot;] = myObj Steve
@Steve: документация не ясна, еслиlua_setupvalue Функция принимает нулевые или единичные индексы. Похоже, что они основаны на одном.
@Steve: функции любого типа могут иметь 0 или более значений.Lua функции (скомпилированный код Lua) будут иметь как минимумone повышать стоимость. Первое повышение, индекс 1, являетсяenvironment для этой функции (именно поэтому каждая функция Lua имеет по крайней мере одну). Что касается последнего, то это зависит от вас. Поместить его в таблицу условий является одним из способов сделать это.
так что в основном - я даже не уверен, что означает этот параметр - это всегда 1? - а кроме того, вам случается знать, как выставить мой c ++ obj только для этой среды? Steve
что касается & quot; почему & quot; являются ли функции глобальными - мне нравится создавать систему событий со сценариями для нескольких объектов, которые используют одну и ту же сигнатуру функции, например, init, так как сценарии, как правило, не создаются разработчиками, я хочу сделать его как можно более безболезненным и не беспокоить никого библиотекарями или модулями - поэтому я хочу убедиться, что каждый сценарий выполняется в своей собственной среде - в любом случае он не получен! Steve

Похожие вопросы