Звучит немного страшно, не так ли?
Немного справочной информации, я хочу загрузить tar-архив, содержащий несколько модулей lua, в мое приложение C # с использованием LuaInterface.Самый простой способ - извлечь эти файлы во временную папку, изменить путь поиска модуля lua и, как обычно, прочитать их с помощью require.Но я не хочу помещать эти сценарии где-нибудь в файловую систему.
Поэтому я подумал, что можно загрузить tar-архив с помощью # ziplib Я знаю, что их многореализаций lua для tar и тому подобного.Но #zlib уже является частью проекта.
После успешной загрузки файла в виде строк (потоков) из архива я смогу передать их в lua.DoString (...) в C # черезLuaInterface.
Но простая загрузка модулей с помощью dostring или dofile не работает, если у модулей есть строка, подобная этой: "module (..., package.seeall)" Есть сообщение об ошибке, например, передача аргумента 1 в ноль,но ожидаемая строка.
Другая проблема в том, что модуль может зависеть от других модулей, которые также находятся в архиве tar.
Одним из возможных решений должно быть определение пользовательского загрузчика, как описано здесь .
Моя идея состоит в том, чтобы реализовать такой загрузчик в C # с помощью #ziplib и отобразить этот загрузчикв стек lua моего приложения на C #.
Кто-нибудь из вас сталкивался с подобной задачей?Есть ли готовые к использованию решения, которые уже решают подобные проблемы?
Файл tar не обязательно должен иметь формат пакета.
Является ли эта идея осуществимой или полностью неосуществимой?
Я написал пример класса для извлечения файлов lua из архива.Этот метод работает как загрузчик и возвращает функцию lua.
namespace LuaInterfaceTest
{
class LuaTarModuleLoader
{
private LuaTarModuleLoader() { }
~LuaTarModuleLoader()
{
in_stream_.Close();
}
public LuaTarModuleLoader(Stream in_stream,Lua lua )
{
in_stream_ = in_stream;
lua_ = lua;
}
public LuaFunction load(string modulename, out string error_message)
{
string lua_chunk = "test=hello";
string filename = modulename + ".lua";
error_message = "Unable to locate the file";
in_stream_.Position = 0; // rewind
Stream gzipStream = new BZip2InputStream(in_stream_);
TarInputStream tar = new TarInputStream(gzipStream);
TarEntry tarEntry;
LuaFunction func = null;
while ((tarEntry = tar.GetNextEntry()) != null)
{
if (tarEntry.IsDirectory)
{
continue;
}
if (filename == tarEntry.Name)
{
MemoryStream out_stream = new MemoryStream();
tar.CopyEntryContents(out_stream);
out_stream.Position = 0; // rewind
StreamReader stream_reader = new StreamReader(out_stream);
lua_chunk = stream_reader.ReadToEnd();
func = lua_.LoadString(lua_chunk, filename);
string dum = func.ToString();
error_message = "No Error!";
break;
}
}
return func;
}
private Stream in_stream_;
private Lua lua_;
}
}
Я пытаюсь зарегистрировать метод загрузки следующим образом в LuaInterface
Lua lua = new Lua();
GC.Collect();
Stream inStream = File.OpenRead("c:\\tmp\\lua_scripts.tar.bz2");
LuaTarModuleLoader tar_loader = new LuaTarModuleLoader(inStream, lua);
lua.DoString("require 'CLRPackage'");
lua.DoString("import \"ICSharpCode.SharpZipLib.dll\"");
lua.DoString("import \"System\"");
lua["container_module_loader"] = tar_loader;
lua.DoString("table.insert(package.loaders, 2, container_module_loader.load)");
lua.DoString("require 'def_sensor'");
Если япопробуйте так, я получу исключение, в то время как вызов требует:
"экземпляр метода 'load' требует ненулевого целевого объекта"
Я пыталсявызовите метод загрузки напрямую, здесь я должен использовать нотацию ":".
lua.DoString("container_module_loader:load('def_sensor')");
Если я вызываю метод таким образом, я попадаю на точку останова в отладчике, который находится поверх метода, так что все работает как положено.
Но если я пытаюсь зарегистрироватьметод с нотацией ":" Я получаю исключение при регистрации метода:
lua.DoString("table.insert(package.loaders, 2, container_module_loader:load)");
"[string" chunk "]: 1: аргументы функции ожидаются рядом с ')'"