Попытка загрузить Penlight модули Lua из C

0

Я начинаю вкладывать свои руки в lua и до сих пор испытывал довольно неприятный опыт. Мне нужно загрузить части penlight, чтобы загрузить "mine.lua", для которого требуется pl.import_into. Мне нужно сделать это с C/C++.

Я использую lua 5.1; использование 5.2 не является опцией atm, поэтому у меня нет luaL_requiref

Грубо мой код выглядит так:

void luaLoad(lua_State* L, const char* f) {
  if (luaL_dofile(L, f) || lua_pcall(L, 0, 0, 0)) {
    const char* err = lua_tostring(L, -1);
    lua_pop(L, -1);
    throw std::runtime_error("Lua load error");
  }
}
int main(void) {
  lua_State *L = luaL_newstate();
  luaL_openlibs(L);
  luaLoad(L, "~/Penlight-1.3.1/lua/pl/compat.lua");
  luaLoad(L, "~/Penlight-1.3.1/lua/pl/utils.lua");
  luaLoad(L, "~/Penlight-1.3.1/lua/pl/import_into.lua");
  luaLoad(L, "mine.lua");
  ...
}

Я начал пытаться загрузить import_into.lua, который требовал utils.lua и транзитивно compat.lua.

В моем методе luaLoad, если я опускаю lua_pcall, utils.lua "не видит" compat.lua:

utils.lua : module 'pl.compat' not found'

Однако с lua_pcall я получаю

attempt to call a table value' error.

Пытается ли загружать penlight из C в корне неправильно?

  • 0
    Какую ОС вы используете? Это расширяет тильды? Здорово.
  • 0
    В случае, если мой комментарий не был ясен: вы знаете о тильде? Это оболочка, которая обрабатывает это, а не ядро. Вы не можете обычно использовать это так. В любом случае, почему бы вашему проекту не иметь файл "bootstrap.lua" и делать там все?
Теги:
lua

1 ответ

2
Лучший ответ

Во-первых: lua_pcall является излишним. luaL_dofile уже выполняет lua_pcall. lua_pop также неверен. Во-вторых: Любая причина, по которой вы не просто изменяете package.path, так что Lua require функция могла найти необходимые модули?

Если вы не можете или не хотите этого делать, есть два подхода:

В дополнение к запуску кода модуля вам также нужно сохранить его результат в таблице package.loaded используя имя модуля в качестве ключа. Таким образом, функция require вызываемая в коде penlight, может найти эти модули позже.

void luaLoad(lua_State* L, char const* m, const char* f) {
  int top = lua_gettop(L);
  if (luaL_dofile(L, f)) {
    const char* err = lua_tostring(L, -1);
    lua_pop(L, 1); /* the 2nd parameter is a number not a stack index! */
    throw std::runtime_error("Lua load error");
  } else {
    lua_settop(L, top+1); /* discard anything but first return value */
    lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); /* get 'package.loaded' */
    lua_pushvalue(L, -2); /* 'lua_setfield' needs the return value at stack top */
    lua_setfield(L, -2, m); /* store return value as 'package.loaded[m]' */
    lus_settop(L, top); /* restore Lua stack */
  }
}

Преимущества в том, что вы можете использовать одну и ту же функцию для запуска mine.lua. Недостатком является то, что вам нужно загрузить модули в правильном порядке, и если один из модулей использует функцию module, код становится немного сложнее (в основном вы переопределяете части функции Lua require).

Второй подход - загрузить, но не запускать модули и поместить загруженный код (который является функцией Lua) в таблицу package.preload с использованием имени модуля в качестве ключа. Функция require может позже поднять их и запустить оттуда.

void luaPreload(lua_State* L, char const* m, char const* f) {
  if (luaL_loadfile(L, f)) {
    char const* err = lua_tostring(L, -1);
    lua_pop(L, 1);
    throw std:runtime_error("Lua load error");
  } else {
    lua_getglobal(L, "package"); /* there is no shorthand for 'package.preload' */
    lua_getfield(L, -1, "preload");
    lua_pushvalue(L, -3); /* 'lua_setfield' needs the function at stack top */
    lua_setfield(L, -2, m); /* store chunk as 'package.preload[m]' */
    lua_pop(L, 3); /* restore Lua stack */
  }
}

Преимущества заключаются в том, что в запросе будут автоматически выполняться модули в правильном порядке, а функция module не требует специальной обработки. Недостатком является то, что вам нужен отдельный код для запуска mine.lua.

Все эти подходы предполагают, что mine.lua использует Lua, require функции для доступа к модулям penlight.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню